Why does this `impl Executor` does not live long enough?

REPRODUCTION: undefined | Rust Explorer

I apologize in advance if the code seems confusing or complex for no apparent reason: this is just a minimal example compared to the real code (which is much more complex and bigger).

I would like to understand why this 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()
    | |____________^

The reason I'm using the trait Executor is because I need to use both DB connections and transactions in my services layer (represented here by team_list).

I can change everything in this code, the trait too.

Can you help me?

Ignoring where the 'static constraint comes from, but perhaps addressing the problem...

I see you already doing this elsewhere:

impl<E: 'static + Executor> TeamTrait for Repo<E> {

The corresponding bound where you're getting an error would be:

    db: &'a mut (impl Executor + 'static),

If it's reasonable that Executor never needs to hold on to something borrowed, you could

-pub trait Executor: Send + Sync {
+pub trait Executor: Send + Sync + 'static {

And then it will be implied everywhere, and you can use

impl<E: Executor> TeamTrait for Repo<E> {
// ...
    db: &'a mut impl Executor,

Wow. This seems to work! But now I'm terrified of what might happen in the future with this change.

If you remove Send from the Boxing the future is fine with lifetimes. Not that you would find that useful in full program.

Why does an error prompt when there is no 'static added? Thank you for your reply

I have tested and found that the db.as_executor() passed in when calling fetch_all caused the lifetime check to fail.
Is it because of the lifetime 'this defined in the associated type, or because of the lifetime restriction in sqlx::executor::Executor<'c> ? Thank you for your reply

I believe it's some form of this bug.

For example.

1 Like

Thank you very much for your reply. I have been thinking about this issue for a long time.

More directly, probably.

Based on comments in that bug, removing the where Self: 'this bound on the GAT may also work around the issue.

pub trait Executor: Send + Sync {
    type Executor<'this>: Send + Sync; // + sqlx::PgExecutor<'this>

    fn _disable_lint(e: Self::Executor<'_>) -> Self::Executor<'_> { e }