Repository: rust
Issue: Confusing diagnostic when forgetting to capture lifetime in a APIT
Labels: A-diagnostics,A-lifetimes,T-compiler,D-terse

### Code

```Rust
trait A<'a> {
    type Assoc;
}

trait B {}

fn f(_: impl for<'a> A<'a, Assoc = impl B>) {}

impl<'a> A<'a> for () {
    type Assoc = &'a u8;
}

impl B for &u8 {}

fn main() {
    f(());
}
```


### Current output

```Shell
error[E0308]: mismatched types
  --> ./t.rs:16:5
   |
16 |     f(());
   |     ^^^^^ one type is more general than the other
   |
   = note: expected reference `&'a _`
              found reference `&_`
note: the lifetime requirement is introduced here
  --> ./t.rs:7:28
   |
7  | fn f(_: impl for<'a> A<'a, Assoc = impl B>) {}
   |                            ^^^^^^^^^^^^^^
```


### Desired output

```Shell
error[E0308]: mismatched types
  --> ./t.rs:16:5
   |
16 |     f(());
   |     ^^^^^ one type is more general than the other
   |
   = note: expected reference `for<'a> &'a _`
              found reference `&'0 _` for some specific lifetime `'0`
   = note: `impl B` can't name `'a`
note: the lifetime requirement is introduced here
  --> ./t.rs:7:28
   |
7  | fn f(_: impl for<'a> A<'a, Assoc = impl B>) {}
   |                            ^^^^^^^^^^^^^^
```


### Rationale and extra context

It is not very clear from the error why `impl B` introduces the lifetime requirement or why we "found" a `&_` (this leaks generalizer impl kinda). Ideally we would explain the actual cause of the error (`impl B` introduces a new generic parameter outside of the scope of `for<'a>`).

I don't like having `for<'a> &'a _` in the desired error either, because it implies that it's a type that exists, but I couldn't come up with a better explanation for the fact that `'a` is from the `for<'a>`...

Maybe we could even suggest `impl for<'a> A<'a, Assoc: B>)` but @BoxyUwU says it's probably hard. We could just lint on `impl Trait<Assoc = impl Other>` as a style thing suggesting `Assoc: Other` since it allows more things.

### Other cases

```Rust
If you add `+ 'a` the diagnostic is a bit better:


trait A<'a> {
    type Assoc;
}

trait B {}

fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}

impl<'a> A<'a> for () {
    type Assoc = &'a u8;
}

impl B for &u8 {}

fn main() {
    f(());
}
```
```
error: `impl Trait` can only mention lifetimes from an fn or impl
 --> ./t.rs:7:45
  |
7 | fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
  |                  -- lifetime declared here  ^^

error[E0308]: mismatched types
  --> ./t.rs:16:5
   |
16 |     f(());
   |     ^^^^^ one type is more general than the other
   |
   = note: expected reference `&'a _`
              found reference `&_`
note: the lifetime requirement is introduced here
  --> ./t.rs:7:28
   |
7  | fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
   |                            ^^^^^^^^^^^^^^^^^^^
```

### Rust Version

```Shell
rustc 1.79.0-nightly (ef8b9dcf2 2024-04-24)
binary: rustc
commit-hash: ef8b9dcf23700f2e2265317611460d3a65c19eff
commit-date: 2024-04-24
host: x86_64-unknown-linux-gnu
release: 1.79.0-nightly
LLVM version: 18.1.4
```


### Anything else?

_No response_