Repository: rust
Issue: Poor diagnostic for closure not returning Result when there is a return Ok/Err in it
Labels: A-diagnostics,T-compiler

<!--
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.
-->

I was doing a refactoring of moving a match arm into a closure and I got confused at the error when it was saying the closure had the wrong type. I think that one part of it is that the error should say something about it being that the closure return type is wrong, not just "expected x type" like it was just a normal variable being the wrong type, and because of this insufficiently specific message, I couldn't really tell what exactly had the wrong type. Additionally, there's a custom improved diagnostic (shown elsewhere below) that this is missing the condition for because there's an explicit return in the closure, leading to this confusing behaviour.

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=35f4adc1e8a72ab59e0a6501259638be

```rust
fn returns_result() -> Result<(), ()> {
    Ok(())
}

fn main() {
    let f = || {
        if false {
            return Err(());
        }
        // do some stuff
        returns_result()?;
        // do some more stuff
        println!("hello world!");
    };

    f();
}
```

The current output is:

```
error[E0308]: mismatched types
  --> src/main.rs:6:16
   |
6  |       let f = || {
   |  ________________^
7  | |         if false {
8  | |             return Err(());
9  | |         }
...  |
13 | |         println!("hello world!");
14 | |     };
   | |_____^ expected enum `Result`, found `()`
   |
   = note:   expected type `Result<_, ()>`
           found unit type `()`
```

<!-- The following is not always necessary. -->
Ideally the output should look like:

```
error[E0277]: the `?` operator can only be used in a closure that returns `Resul
t` or `Option` (or another type that implements `FromResidual`)
  --> src/main.rs:8:25
   |
6  |       let f = || {
   |  _____________-
7  | |         // do some stuff
8  | |         returns_result()?;
   | |                         ^ cannot use the `?` operator in a closure that r
eturns `()`
9  | |         // do some more stuff
10 | |         println!("hello world!");
11 | |     };
   | |_____- this function should return `Result` or `Option` to accept `?`
   |
   = help: the trait `FromResidual<Result<Infallible, ()>>` is not implemented f
or `()`
   = note: required by `from_residual`
```

<!--
If the problem is not self-explanatory, please provide a rationale for the
change.
-->

If you delete the `if false { ... }` block, it results in the desired output.

<!--
If dramatically different output is caused by small changes, consider also
adding them here.

If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions. The output might also be
different depending on the Edition.
-->

rustc 1.55.0-nightly (8b87e8539 2021-07-08)