Repository: rust
Issue: Lifetime error in scoped spawn doesn't identify the captured lifetime
Labels: A-diagnostics,A-lifetimes,A-closures,T-compiler,D-confusing

This is a self-contained reproducer from https://github.com/rayon-rs/rayon/issues/871

Given the following code:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=c51857b253b7171e3b2c1083e7f8aa0a

```rust
// Library code implementing a scoped spawn:

use std::marker::PhantomData;

struct Scope<'scope> {
    marker: PhantomData<dyn FnOnce(&Self) + 'scope>,
}

impl<'scope> Scope<'scope> {
    fn spawn(&self, _f: impl FnOnce(&Self) + 'scope) {
        todo!("run the task before the end of 'scope");
    }
}

fn scope<'scope>(f: impl FnOnce(&Scope<'scope>)) {
    let s = Scope { marker: PhantomData };
    f(&s);
}

// User code trying to make sense of lifetimes:

struct Test<'scope_ref, 'scope, 'value> {
    value: &'value usize,
    scope: &'scope_ref Scope<'scope>,
}

impl<'scope_ref, 'scope, 'value> Test<'scope_ref, 'scope, 'value>
where
    'scope: 'scope_ref,
    'value: 'scope,
{
    fn test(&self) {
        self.scope.spawn(|scope| {
            let t = Test { scope, value: self.value };
            // Ignore the fact that this will respawn forever.
            t.test();
        });
    }
}

fn main() {
    let value = 0;

    scope(|scope| {
        let t = Test { scope, value: &value };
        t.test();
    });
}
```

The current output is:

```
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/lib.rs:33:26
   |
33 |           self.scope.spawn(|scope| {
   |  __________________________^
34 | |             let t = Test { scope, value: self.value };
35 | |             // Ignore the fact that this will respawn forever.
36 | |             t.test();
37 | |         });
   | |_________^
   |
note: first, the lifetime cannot outlive the lifetime `'scope_ref` as defined on the impl at 27:6...
  --> src/lib.rs:27:6
   |
27 | impl<'scope_ref, 'scope, 'value> Test<'scope_ref, 'scope, 'value>
   |      ^^^^^^^^^^
note: ...so that the types are compatible
  --> src/lib.rs:33:26
   |
33 |           self.scope.spawn(|scope| {
   |  __________________________^
34 | |             let t = Test { scope, value: self.value };
35 | |             // Ignore the fact that this will respawn forever.
36 | |             t.test();
37 | |         });
   | |_________^
   = note: expected `(&&Test<'_, 'scope, '_>,)`
              found `(&&Test<'scope_ref, 'scope, 'value>,)`
note: but, the lifetime must be valid for the lifetime `'scope` as defined on the impl at 27:18...
  --> src/lib.rs:27:18
   |
27 | impl<'scope_ref, 'scope, 'value> Test<'scope_ref, 'scope, 'value>
   |                  ^^^^^^
note: ...so that the types are compatible
  --> src/lib.rs:33:20
   |
33 |         self.scope.spawn(|scope| {
   |                    ^^^^^
   = note: expected `&Scope<'_>`
              found `&Scope<'scope>`
```

It's true that this spawn closure does not outlive the `'scope` lifetime, but this output doesn't really help us figure out **why**. The closure captures `self` with its anonymous lifetime, but it could be fixed like so:

```patch
-        self.scope.spawn(|scope| {
-            let t = Test { scope, value: self.value };
+        let value = self.value;
+        self.scope.spawn(move |scope| {
+            let t = Test { scope, value };
```

---

PS: This can also be fixed by switching to 2021 edition, I suppose due to [RFC 2229](https://rust-lang.github.io/rfcs/2229-capture-disjoint-fields.html) disjoint capturing. This surprises me, because I would have thought that would capture a reference to `self.value`, which would still have a lifetime issue, but in MIR it appears to be copying it like a `move` closure.