Repository: rust
Issue: Higher-Rank Trait Bounds: incorrect (or misleading) diagnostic
Labels: A-diagnostics,A-lifetimes,A-closures,T-compiler,A-impl-trait,D-confusing,D-terse,A-higher-ranked

<!--
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.
-->

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5c03cd34558f9bc8662eac3ff255190e

```rust
pub struct Value {
    a: String,
}

pub struct Borrowed<'a> {
    b: &'a str,
}

pub fn parse(a: &Value) -> Borrowed<'_> {
    Borrowed { b: &a.a }
}

pub fn not<T>(predicate: impl Fn(&T) -> bool) -> impl Fn(&T) -> bool {
    move |t: &T| !predicate(t)
}

/// Transform a predicate on `Borrowed`s into a predicate for `Value`s
pub fn borrowed(predicate: impl for<'a> Fn(&Borrowed<'_>) -> bool) -> impl Fn(&Value) -> bool {
    move |t: &Value| {
        let parsed = parse(t);
        predicate(&parsed)
    }
}

pub fn is_borrowed_cool() -> impl for<'a> Fn(&Borrowed<'a>) -> bool {
    |b| true
}

pub fn compose_predicates() {
    let a = not(is_borrowed_cool());
    let b = borrowed(is_borrowed_cool());
    // I would like this to compile. It doesn't though, and it generates
    // an incorrect diagnostic.
    let c = borrowed(not(is_borrowed_cool()));
}
```

The current output is:

```
error[E0308]: mismatched types
  --> src/lib.rs:34:13
   |
13 | pub fn not<T>(predicate: impl for<'a> Fn(&'a T) -> bool) -> impl for<'a> Fn(&'a T) -> bool {
   |                                                             ------------------------------
   |                                                             |
   |                                                             one of the expected opaque types
   |                                                             one of the found opaque types
...
25 | pub fn is_borrowed_cool() -> impl for<'a> Fn(&Borrowed<'a>) -> bool {
   |                              --------------------------------------
   |                              |
   |                              one of the expected opaque types
   |                              one of the found opaque types
...
34 |     let c = borrowed(not(is_borrowed_cool()));
   |             ^^^^^^^^ lifetime mismatch
   |
   = note: expected associated type `<impl for<'a> Fn<(&'a Borrowed<'_>,)> as FnOnce<(&Borrowed<'_>,)>>::Output`
              found associated type `<impl for<'a> Fn<(&'a Borrowed<'_>,)> as FnOnce<(&Borrowed<'_>,)>>::Output`
note: the lifetime requirement is introduced here
  --> src/lib.rs:18:62
   |
18 | pub fn borrowed(predicate: impl for<'a> Fn(&Borrowed<'_>) -> bool) -> impl Fn(&Value) -> bool {
   |                                                              ^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
```

Note the following lines specially:

```
   = note: expected associated type `<impl for<'a> Fn<(&'a Borrowed<'_>,)> as FnOnce<(&Borrowed<'_>,)>>::Output`
              found associated type `<impl for<'a> Fn<(&'a Borrowed<'_>,)> as FnOnce<(&Borrowed<'_>,)>>::Output`
```

where the expected and the found types are the same. I'm not sure if this is a compiler bug because I'm not very familiar
with HRTBs, but the diagnostic could be better. I can't really propose the better diagnostic because I don't know what's wrong
with my code.

The error is the same on nightly and beta.

(Edit: simplified the code a bit)