Repository: rust
Issue: LGAT associated type bounds diagnostics are not great
Labels: A-diagnostics,T-compiler,requires-nightly,A-GATs

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.

If you cannot produce a minimal reproduction case (something that would work in
isolation), please provide the steps or even link to a repository that causes
the problematic output to occur.
-->

Tested on nightly 2022-07-21.

Illustrating as a edit-compile cycle:

```rust
#![feature(generic_associated_types)]

use core::future::Future;

trait Task {
    type Output<'a>: 'a + Future<Output = ()>
    where
        Self: 'a;
    fn call(&mut self) -> Self::Output<'_>;
}

type DynTask = dyn Task<Output = Box<dyn Future<Output = ()>>>;
```

```
error[E0107]: missing generics for associated type `Task::Output`
  --> src/lib.rs:12:25
   |
12 | type DynTask = dyn Task<Output = Box<dyn Future<Output = ()>>>;
   |                         ^^^^^^ expected 1 lifetime argument
   |
note: associated type defined here, with 1 lifetime parameter: `'a`
  --> src/lib.rs:6:10
   |
6  |     type Output<'a>: 'a + Future<Output = ()>
   |          ^^^^^^ --
help: add missing lifetime argument
   |
12 | type DynTask = dyn Task<Output<'a> = Box<dyn Future<Output = ()>>>;
   |                         ~~~~~~~~~~
```

Apply the suggestion.

```rust
type DynTask = dyn Task<Output<'a> = Box<dyn Future<Output = ()>>>;
```

```
error[E0261]: use of undeclared lifetime name `'a`
  --> src/lib.rs:12:32
   |
12 | type DynTask = dyn Task<Output<'a> = Box<dyn Future<Output = ()>>>;
   |                                ^^ undeclared lifetime
   |
   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
   |
12 | type DynTask = dyn for<'a> Task<Output<'a> = Box<dyn Future<Output = ()>>>;
   |                    +++++++
help: consider introducing lifetime `'a` here
   |
12 | type DynTask<'a> = dyn Task<Output<'a> = Box<dyn Future<Output = ()>>>;
   |             ++++
```

That looks wrong, let me try:

```rust
type DynTask = dyn Task<for<'a> Output<'a> = Box<dyn Future<Output = ()>>>;
```

```
error: `for<...>` is not allowed on associated type bounds
  --> src/lib.rs:12:25
   |
12 | type DynTask = dyn Task<for<'a> Output<'a> = Box<dyn Future<Output = ()>>>;
   |                         ^^^^^^^^^^^^^^^^^^
```

Okay, let's do what the compiler suggested

```rust
type DynTask = dyn for<'a> Task<Output<'a> = Box<dyn Future<Output = ()>>>;
```

```
warning: type alias `DynTask` is never used
  --> src/lib.rs:12:6
   |
12 | type DynTask = dyn for<'a> Task<Output<'a> = Box<dyn Future<Output = ()>>>;
   |      ^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: `playground` (lib) generated 1 warning
```

Success! Time to use it...

```
error[E0038]: the trait `Task` cannot be made into an object
  --> src/lib.rs:14:18
   |
14 | fn takes(_: &mut DynTask) {}
   |                  ^^^^^^^ `Task` cannot be made into an object
   |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
  --> src/lib.rs:6:10
   |
5  | trait Task {
   |       ---- this trait cannot be made into an object...
6  |     type Output<'a>: 'a + Future<Output = ()>
   |          ^^^^^^ ...because it contains the generic associated type `Output`
   = help: consider moving `Output` to another trait
```

🙃