Async closures are not allowed to reference all captured lifetimes if one of them is invariant · Issue #123241 · rust-lang/rust (original) (raw)

Full example

async fn go<'a>(value: &'a i32) { let closure = async |scope: ScopeRef<'_, 'a>| { let _future1 = scope.spawn(async { let _v = *value; }); }; }

yields

error: lifetime may not live long enough
  --> examples/repro.rs:52:63
   |
52 |       let closure = async |scope: ScopeRef<'_, 'a, i32>| -> i32 {
   |  ___________________-------------------------------------------_^
   | |                   |                      |
   | |                   |                      let's call the lifetime of this reference `'2`
   | |                   lifetime `'1` represents this closure's body
53 | |         let _future1 = scope.spawn(async { value });
54 | |         22
55 | |     };
   | |_____^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
   |
   = note: closure implements `Fn`, so references to captured variables can't escape the closure
   = note: requirement occurs because of the type `Scope<'_, '_, i32>`, which makes the generic argument `'_` invariant
   = note: the struct `Scope<'scope, 'env, R>` is invariant over the parameter `'scope`

closure was supposed to return data with lifetime '2 ('scope) but it is returning data with lifetime '1 (closure body)

It's reasonable that we would create a lifetime representing the closure body, but naturally, the future should be allowed to reference it. The invariant lifetime must be mucking things up somehow.

(spawn has no lifetime params so I would not expect there to be a new lifetime created when it is called.)

note: closure implements Fn, so references to captured variables can't escape the closure

The closure definitely shouldn't try to implement Fn in this case, I don't know why it does.

note: requirement occurs because of the type Scope<'_, '_, i32>, which makes the generic argument '_ invariant
note: the struct Scope<'scope, 'env, R> is invariant over the parameter 'scope

It's correct that this lifetime is invariant. We must write to a vec of futures that outlive 'scope, so any variance would be unsound.

cc @compiler-errors