Repository: rust
Issue: Suggest updating type alias in this case where it causes a compile error
Labels: A-diagnostics,A-lifetimes,T-compiler,A-suggestion-diagnostics,D-confusing,D-terse

Given the following code: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=dc49c7cda737c71feb919490edfa4578)

```rust
fn main() {
    let non_copy = String::new();

    type F = dyn Fn();
    let f: &F = &|| { &non_copy; };

    fn takes_dyn_ref(_: &dyn Fn()) {}

    takes_dyn_ref(f);

    drop(non_copy);
}
```

The current output is:

```
Compiling playground v0.0.1 (/playground)
error[[E0597]](https://doc.rust-lang.org/stable/error-index.html#E0597): `non_copy` does not live long enough
  [--> src/main.rs:5:24
](https://play.rust-lang.org/#)   |
5  |     let f: &F = &|| { &non_copy; };
   |            --    --    ^^^^^^^^ borrowed value does not live long enough
   |            |     |
   |            |     value captured here
   |            type annotation requires that `non_copy` is borrowed for `'static`
...
12 | }
   | - `non_copy` dropped here while still borrowed

error[[E0505]](https://doc.rust-lang.org/stable/error-index.html#E0505): cannot move out of `non_copy` because it is borrowed
  [--> src/main.rs:11:10
](https://play.rust-lang.org/#)   |
5  |     let f: &F = &|| { &non_copy; };
   |            --    --    -------- borrow occurs due to use in closure
   |            |     |
   |            |     borrow of `non_copy` occurs here
   |            type annotation requires that `non_copy` is borrowed for `'static`
...
11 |     drop(non_copy);
   |          ^^^^^^^^ move out of `non_copy` occurs here

Some errors have detailed explanations: E0505, E0597.
For more information about an error, try `rustc --explain E0505`.
error: could not compile `playground` due to 2 previous errors
```

The following code compiles: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4c30922ee1d652a8df907b24616a0b8d)

```rust
fn main() {
    let non_copy = String::new();

    type F<'a> = dyn Fn() + 'a;
    let f: &F<'_> = &|| { &non_copy; };

    fn takes_dyn_ref(_: &dyn Fn()) {}

    takes_dyn_ref(f);

    drop(non_copy);
}
```

As does entirely removing the type alias: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2dbd102aa9f6b6b9e359588b3c63eec4)

```rust
fn main() {
    let non_copy = String::new();

    let f: &dyn Fn() = &|| { &non_copy; };

    fn takes_dyn_ref(_: &dyn Fn()) {}

    takes_dyn_ref(f);

    drop(non_copy);
}
```

It took me more time than I would have liked to figure out that was the way to address the compile error, when I encountered a simlar in a real project. The parts that were reduced to `takes_dyn_ref` and `drop` in this example were from two different dependencies. Also, the part that was reduced to `non_copy` was also from one of those dependencies, and cannot be meaningfully copied, while preserving the intended semantics. The type alias was one that I had written.

So, I think in this case the the above two options would have been more or less the only options to make the code compile, while preserving the intended semantics.

I think that ideally the output should recommend one or both of those options. For instance, it could contain something like:
```
help: Add a lifetime parameter to the type alias and specify the lifetime
  |
4 |     type F<'a> = dyn Fn() + 'a;
5 |     let f: &F<'_> = &|| { &non_copy; };
  |              
```
Or maybe it could suggest inlining the aliased type, and removing the type alias.