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

error: X does not live long enough doesn't provide enough context #111852

Open
frederikhors opened this issue May 22, 2023 · 4 comments
Open

error: X does not live long enough doesn't provide enough context #111852

frederikhors opened this issue May 22, 2023 · 4 comments
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue

Comments

@frederikhors
Copy link

frederikhors commented May 22, 2023

REPRODUCTION: https://www.rustexplorer.com/b/oe3uh4

error:

error: `impl Executor` does not live long enough
   --> src/main.rs:136:5
    |
136 | /     async move {
137 | |         dbg!("I'm:", user);
138 | |
139 | |         let mut store = store.unwrap_or_default();
...   |
169 | |     }
170 | |     .boxed()
    | |____________^

Some code:

fn query_teams<'a>(
    user: &'a str,
    db: &'a mut impl Executor,
    store: Option<Store>,
    with_player: bool,
) -> BoxFuture<'a, Store> {
    async move {
        dbg!("I'm:", user);

        let mut store = store.unwrap_or_default();

        let mut query = sqlx::QueryBuilder::new(r#"SELECT "teams".*" FROM "teams"#);

        let teams = query
            .build_query_as::<Team>()
            .fetch_all(db.as_executor())
            .await
            .unwrap();

        for team in teams {
            store.teams.insert(team.id.to_string(), team);
        }

        if with_player {
            store = query_players(user, db, Some(store), false).await;
        }

        store
    }
    .boxed()
}
error: `impl Executor` does not live long enough
   --> src/main.rs:136:5
    |
136 | /     async move {
137 | |         dbg!("I'm:", user);
138 | |
139 | |         let mut store = store.unwrap_or_default();
...   |
169 | |     }
170 | |     .boxed()
    | |____________^

Meta

rustc 1.69.0 (84c898d65 2023-04-16)
binary: rustc
commit-hash: 84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc
commit-date: 2023-04-16
host: x86_64-pc-windows-msvc
release: 1.69.0
LLVM version: 15.0.7
@frederikhors frederikhors added the C-bug Category: This is a bug. label May 22, 2023
@fee1-dead fee1-dead added the E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example label May 24, 2023
@fee1-dead
Copy link
Member

simplified a bit using perses, still need to eliminate the dependency though.

use futures::future::{BoxFuture, FutureExt};

trait Executor: Send {
    type Executor<'this>: sqlx::PgExecutor<'this>
    where
        Self: 'this;
    fn as_executor(&mut self) -> Self::Executor<'_>;
}

struct Store {}

#[derive(sqlx::FromRow)]
struct Team {}

fn query_teams(user: &str, db: impl Executor, store: Store) -> BoxFuture<Store> {
    async move {
        let query = sqlx::QueryBuilder::new(r#"SELECT "teams".*" FROM "teams"#);
        query
            .build_query_as::<Team>()
            .fetch_all(db.as_executor())
            .await;
        store
    }
    .boxed()
}

@jyn514 jyn514 added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related A-async-await Area: Async & Await labels May 26, 2023
@fee1-dead fee1-dead changed the title Maybe a bad-error-message? error: X does not live long enough doesn't provide enough context May 30, 2023
@WaffleLapkin
Copy link
Member

Here is, what I believe is, the root cause/MCVE of this issue (play):

trait G: Send {
    type Gat<'l>: Send
    where
        Self: 'l;

    fn as_gat(&self) -> Self::Gat<'_>;
}

fn a(g: impl G) {
    let _: &dyn Send = &async move {
        let _gat = g.as_gat();
        async{}.await
    };
}

It looks like this is what happens:

  1. Proving async{}: Send requires that typeof(_gat): Send (because it lives across an .await point)
  2. typeof(_gat): Send requires Self: 'l
  3. impl G: 'l is the problem

@WaffleLapkin WaffleLapkin added S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue and removed E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels May 30, 2023
@tmandry tmandry added F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. labels Jun 5, 2023
@eholk eholk added the AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. label Jun 5, 2023
@QuineDot
Copy link

QuineDot commented Jun 9, 2023

@WaffleLapkin
Copy link
Member

@QuineDot note that this is not always possible, sometimes such bound is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue
Projects
None yet
Development

No branches or pull requests

7 participants