Repository: rust
Issue: Imprecise error message for tuples with explicit type annotations
Labels: A-diagnostics,T-compiler

## Issue

Consider the following code ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f565a2698f3decfb6f2e40cb9fb882e2)):

```rust
fn main() {
    let foo = [1, 2, 3, 4];
    let bar: (Vec<i32>, Vec<i64>) = foo.iter().partition(|r| **r < 3);
    
    println!("{:?}", bar);
}
```

The current output as of a recent nightly

```
Compiling playground v0.0.1 (/playground)
error[[E0308]](https://doc.rust-lang.org/stable/error-index.html#E0308): mismatched types
 --> src/main.rs:3:37
  |
3 |     let bar: (Vec<i32>, Vec<i64>) = foo.iter().partition(|r| **r < 3);
  |              --------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found `i32`
  |              |
  |              expected due to this
  |
  = note: expected tuple `(Vec<i32>, Vec<i64>)`
             found tuple `(_, _)`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
```

What the error's actually saying is "partition() returns a tuple of two elements of the same type". However, the error message as written suggests the whole expression returns an `i32`, since the arrows point to the entire expression. Additionally, since the "`expected due to this`" message the points to my explicit type annotations, I interpret the error message on the LHS of the let-binding to mean "an `i64` is expected to satisfy typechecking on the LHS of the let-binding".

Although obvious in retrospect, I spent several seconds staring at those lines without the error clicking. Only after looking at the "`note: expected tuple`" line (i.e. the message specifically mentioned the tuple), did I realize that rustc didn't like the type of one of the tuple's elements, rather than the whole tuple, and gave error messages accordingly.

I think the error could be improved by moving the dashed line on the LHS of the let-binding to emphasize only the (first?) mismatched tuple element, and changing the message on the RHS of the binding to reflect which tuple element caused the mismatch. I eventually
understood that `rustc` was focused on writing errors for a specific tuple element by the "`note: expected tuple`" line, but it took me longer than I'd like to make the connection. I think better error output might look like this:

```
Compiling playground v0.0.1 (/playground)
error[[E0308]](https://doc.rust-lang.org/stable/error-index.html#E0308): mismatched types
 --> src/main.rs:3:37
  |
3 |     let bar: (Vec<i32>, Vec<i64>) = foo.iter().partition(|r| **r < 3);
  |                        ----------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64` on tuple element 1, found `i32`
  |                        |
  |                        expected due to this element
  |
  = note: expected tuple `(Vec<i32>, Vec<i64>)`
             found tuple `(_, _)`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
```

## Extra Information

```sh
wjones@DietPi:~/src/rust/pi-ctl$ rustc -Vv
rustc 1.64.0-nightly (4d6d601c8 2022-07-26)
binary: rustc
commit-hash: 4d6d601c8a83284d6b23c253a3e2a060fd197316
commit-date: 2022-07-26
host: armv7-unknown-linux-gnueabihf
release: 1.64.0-nightly
LLVM version: 14.0.6
```


<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":null}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->