Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot infer lifetime with disjoint capture. #88431

Closed
ehuss opened this issue Aug 28, 2021 · 1 comment · Fixed by #88467
Closed

Cannot infer lifetime with disjoint capture. #88431

ehuss opened this issue Aug 28, 2021 · 1 comment · Fixed by #88467
Assignees
Labels
A-closures Area: Closures (`|…| { … }`) A-edition-2021 Area: The 2021 edition C-bug Category: This is a bug.

Comments

@ehuss
Copy link
Contributor

ehuss commented Aug 28, 2021

I tried this code:

#![warn(rust_2021_incompatible_closure_captures)]
#![feature(capture_disjoint_fields)]
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;

pub struct GameMode {}

struct GameStateManager<'a> {
    gamestate_stack: Vec<Box<dyn GameState<'a> + 'a>>,
}

pub trait GameState<'a> {}

async fn construct_gamestate_replay<'a>(
    _gamemode: &GameMode,
    _factory: &mut GameStateManager<'a>,
) -> Box<dyn GameState<'a> + 'a> {
    unimplemented!()
}

type FutureGameState<'a, 'b> = Pin<Box<dyn Future<Output = Box<dyn GameState<'a> + 'a>> + 'b>>;

struct MenuOption<'a> {
    command: Box<dyn for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a>,
}

impl<'a> MenuOption<'a> {
    fn new(
        _command: impl for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a,
    ) -> Self {
        unimplemented!()
    }
}

struct MenuState<'a> {
    options: Vec<MenuOption<'a>>,
}

impl<'a> GameState<'a> for MenuState<'a> {}

pub async fn get_replay_menu<'a>(
    gamemodes: &'a HashMap<&str, GameMode>,
) -> Box<dyn GameState<'a> + 'a> {
    let recordings: Vec<String> = vec![];
    let _ = recordings
        .into_iter()
        .map(|entry| {
            MenuOption::new(move |f| {
                Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f))
            })
        })
        .collect::<Vec<_>>();

    todo!()
}

fn main() {}

This compiles successfully without disjoint captures, but with them enable gives a lifetime error:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:42:5
   |
42 |     gamemodes: &'a HashMap<&str, GameMode>,
   |     ^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 41:30...
  --> src/main.rs:41:30
   |
41 | pub async fn get_replay_menu<'a>(
   |                              ^^
note: ...so that the expression is assignable
  --> src/main.rs:42:5
   |
42 |     gamemodes: &'a HashMap<&str, GameMode>,
   |     ^^^^^^^^^
   = note: expected `&HashMap<&str, GameMode>`
              found `&'a HashMap<&str, GameMode>`
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the body at 48:29...
  --> src/main.rs:48:29
   |
48 |               MenuOption::new(move |f| {
   |  _____________________________^
49 | |                 Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f))
50 | |             })
   | |_____________^
note: ...so that the expression is assignable
  --> src/main.rs:49:17
   |
49 |                 Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f))
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Pin<Box<dyn Future<Output = Box<dyn GameState<'_>>>>>`
              found `Pin<Box<dyn Future<Output = Box<dyn GameState<'_>>>>>`

I would expect either it to compile successfully, or the rust_2021_incompatible_closure_captures lint to provide a suggestion to make it compile successfully.

Found in the 2021 crater run for https://crater-reports.s3.amazonaws.com/pr-87190-3/try%23a7a572ce3edd6d476191fbfe92c9c1986e009b34/gh/stefan-blair.tetrust/log.txt

(Sorry, didn't narrow the example down further, or if this is a duplicate.)

Meta

rustc --version --verbose:

rustc 1.56.0-nightly (ac50a5335 2021-08-27)
binary: rustc
commit-hash: ac50a53359328a5d7f2f558833e63d59d372e4f7
commit-date: 2021-08-27
host: x86_64-apple-darwin
release: 1.56.0-nightly
LLVM version: 13.0.0

cc @rust-lang/wg-rfc-2229

@ehuss ehuss added A-closures Area: Closures (`|…| { … }`) C-bug Category: This is a bug. A-edition-2021 Area: The 2021 edition labels Aug 28, 2021
@Mark-Simulacrum Mark-Simulacrum added A-edition-2021 Area: The 2021 edition and removed A-edition-2021 Area: The 2021 edition labels Aug 28, 2021
@arora-aman
Copy link
Member

@rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: Closures (`|…| { … }`) A-edition-2021 Area: The 2021 edition C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants