Repository: rust
Issue: Misleading error messages on closure lifetimes, instead of type
Labels: A-diagnostics,T-compiler

Given the following code: [play.rust-lang.org](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=23c84402992527afdcaf1491430fd8af)

```rust
/// I added this when figuring out the error message
fn not_great(){
    let not_zero = |&x| x != 0;
    [0, 1, 2].iter().filter(not_zero);
}

/// Not great, but would have lead me to checking deref count
fn not_great2(){
    [(0, false), (1, false), (2, false)].iter().filter(|&(x, _)| x != 0);
}

/// this would work, but I wanted to use `not_zero` multiple times, so I started with closure
fn _works_ok() {
    [(0, false), (1, false), (2, false)].iter().filter(|&&(x, _)| x != 0).all(|_|true);
}

/// this is very simplified case of the issue
fn misleading() {
    let not_zero = |&(x, _)| x != 0;
    [(0, false), (1, false), (2, false)].iter().filter(not_zero);
}

/// this is full example of the issues, that now not even `all` compiles with very strange error message
fn misleading2() {
    let not_zero = |&(x, _)| x != 0;
    [(0, false), (1, false), (2, false)].iter().filter(not_zero).all(|_|true);
}

/// when deref is corrected, it errors out on "implementation of `FnOnce` is not general enough"
fn very_misleading() {
    let not_zero = |&&(x, _)| x != 0;
    [(0, false), (1, false), (2, false)].iter().filter(not_zero);
}

/// and this is the most unreadable one, that again does not offer any hint how to fix it, but I do not even have a clue what is wrong
fn very_misleading2() {
    let not_zero = |&&(x, _)| x != 0;
    [(0, false), (1, false), (2, false)].iter().filter(not_zero).all(|_|true);
}
```
I wanted to use `not_zero` multiple times, so I did not even tried to put it directly to the `filter` 

The current output is:

```
Compiling playground v0.0.1 (/playground)
error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): can't compare `&{integer}` with `{integer}`
 --> src/main.rs:4:27
  |
4 |     let not_zero = |&x| x != 0;
  |                           ^^ no implementation for `&{integer} == {integer}`
  |
  = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): can't compare `&{integer}` with `{integer}`
  --> src/main.rs:10:68
   |
10 |     [(0, false), (1, false), (2, false)].iter().filter(|&(x, _)| x != 0);
   |                                                                    ^^ no implementation for `&{integer} == {integer}`
   |
   = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`

error[[E0631]](https://doc.rust-lang.org/stable/error-index.html#E0631): type mismatch in closure arguments
   --> src/main.rs:21:56
    |
20  |     let not_zero = |&(x, _)| x != 0;
    |                    ---------------- found signature of `fn(&(_, _)) -> _`
21  |     [(0, false), (1, false), (2, false)].iter().filter(not_zero);
    |                                                 ------ ^^^^^^^^ expected signature of `for<'r> fn(&'r &({integer}, bool)) -> _`
    |                                                 |
    |                                                 required by a bound introduced by this call
    |
note: required by a bound in `filter`

error[[E0631]](https://doc.rust-lang.org/stable/error-index.html#E0631): type mismatch in closure arguments
   --> src/main.rs:27:56
    |
26  |     let not_zero = |&(x, _)| x != 0;
    |                    ---------------- found signature of `fn(&(_, _)) -> _`
27  |     [(0, false), (1, false), (2, false)].iter().filter(not_zero).all(|_|true);
    |                                                 ------ ^^^^^^^^ expected signature of `for<'r> fn(&'r &({integer}, bool)) -> _`
    |                                                 |
    |                                                 required by a bound introduced by this call
    |
note: required by a bound in `filter`

error[[E0599]](https://doc.rust-lang.org/stable/error-index.html#E0599): the method `all` exists for struct `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:26:20: 26:36]>`, but its trait bounds were not satisfied
  --> src/main.rs:27:66
   |
26 |       let not_zero = |&(x, _)| x != 0;
   |                      ----------------
   |                      |
   |                      doesn't satisfy `<_ as FnOnce<(&&({integer}, bool),)>>::Output = bool`
   |                      doesn't satisfy `_: FnMut<(&&({integer}, bool),)>`
27 |       [(0, false), (1, false), (2, false)].iter().filter(not_zero).all(|_|true);
   |                                                                    ^^^ method cannot be called on `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:26:20: 26:36]>` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `<[closure@src/main.rs:26:20: 26:36] as FnOnce<(&&({integer}, bool),)>>::Output = bool`
           which is required by `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:26:20: 26:36]>: Iterator`
           `[closure@src/main.rs:26:20: 26:36]: FnMut<(&&({integer}, bool),)>`
           which is required by `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:26:20: 26:36]>: Iterator`

error: implementation of `FnOnce` is not general enough
  --> src/main.rs:33:49
   |
33 |     [(0, false), (1, false), (2, false)].iter().filter(not_zero);
   |                                                 ^^^^^^ implementation of `FnOnce` is not general enough
   |
   = note: closure with signature `fn(&'2 &(i32, bool)) -> bool` must implement `FnOnce<(&'1 &(i32, bool),)>`, for any lifetime `'1`...
   = note: ...but it actually implements `FnOnce<(&'2 &(i32, bool),)>`, for some specific lifetime `'2`

error[[E0599]](https://doc.rust-lang.org/stable/error-index.html#E0599): the method `all` exists for struct `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:38:20: 38:37]>`, but its trait bounds were not satisfied
  --> src/main.rs:39:66
   |
38 |       let not_zero = |&&(x, _)| x != 0;
   |                      -----------------
   |                      |
   |                      doesn't satisfy `<_ as FnOnce<(&&({integer}, bool),)>>::Output = bool`
   |                      doesn't satisfy `_: FnMut<(&&({integer}, bool),)>`
39 |       [(0, false), (1, false), (2, false)].iter().filter(not_zero).all(|_|true);
   |                                                                    ^^^ method cannot be called on `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:38:20: 38:37]>` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `<[closure@src/main.rs:38:20: 38:37] as FnOnce<(&&({integer}, bool),)>>::Output = bool`
           which is required by `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:38:20: 38:37]>: Iterator`
           `[closure@src/main.rs:38:20: 38:37]: FnMut<(&&({integer}, bool),)>`
           which is required by `Filter<std::slice::Iter<'_, ({integer}, bool)>, [closure@src/main.rs:38:20: 38:37]>: Iterator`

Some errors have detailed explanations: E0277, E0599, E0631.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground` due to 7 previous errors
```

Ideally the output should look like:

```
Hint: try adding type:
let not_zero = |&&(x, _)| x != 0;
                ^ expected && instead of &
(if it would actually work)

Hint: try adding type:
let not_zero = |&&(x, _): &&(i32, bool)| x != 0;
                ^-------^^^^^^^^^^^^^^^ expected full type
```
sorry not really good at formulating the exact message 😞 to look like the good error messages with hint to fix things

> If dramatically different output is caused by small changes, consider also
adding them here.

I added it as `misleading2` and `very_misleading2` functions, which are more close to my code, but at that point I was already figuring it out outside of real code on the simplified examples.