Repository: rust
Issue: Improve suggestion when TryFrom trait bound not satisified due to missing dereference
Labels: A-diagnostics,A-trait-system,T-compiler,D-confusing,D-newcomer-roadblock,D-terse

Hi!

Whilst working through [Rustlings](https://github.com/rust-lang/rustlings) exercise [try_from_into](https://github.com/rust-lang/rustlings/blob/df25684cb79f8413915e00b5efef29369849cef1/exercises/conversions/try_from_into.rs), I encountered a few confusing compiler messages, particularly once I tried to fix the original issue.

I wasn't quite sure how to phrase the issue title - please rename as needed :-)

Given the following code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=11706b8dd1bef0c09d48be82bd88700e

```rust
use std::convert::{TryFrom, TryInto};
use std::error;

#[derive(Debug, PartialEq)]
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

impl TryFrom<&[i16]> for Color {
    type Error = Box<dyn error::Error>;
    fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {
        match slice {
            [red, green, blue] => Ok(Color {
                red: red.try_into()?,
                green: green.try_into()?,
                blue: blue.try_into()?,
            }),
            _ => Err("Invalid slice".into()),
        }
    }
}

fn main() {
    let v = vec![183, 65, 14];
    let c = Color::try_from(&v[..]);
    println!("{:?}", c);
}
```

The current output is:

```
error[E0277]: the trait bound `u8: From<&i16>` is not satisfied
  --> src/main.rs:16:26
   |
16 |                 red: red.try_into()?,
   |                          ^^^^^^^^ the trait `From<&i16>` is not implemented for `u8`
   |
   = help: the following implementations were found:
             <u8 as From<NonZeroU8>>
             <u8 as From<bool>>
   = note: required because of the requirements on the impl of `Into<u8>` for `&i16`
   = note: required because of the requirements on the impl of `TryFrom<&i16>` for `u8`
   = note: required because of the requirements on the impl of `TryInto<u8>` for `&i16`
...
```

Ideally the output should either suggest dereferencing red/green/blue, using:

```rust
        match slice {
            [red, green, blue] => Ok(Color {
                red: (*red).try_into()?,
                green: (*green).try_into()?,
                blue: (*blue).try_into()?,
            }),
            _ => Err("Invalid slice".into()),
        }
```

Or else even better suggest changing the syntax used in that match arm (`[red, green, blue]` -> `&[red, green, blue]`):

```rust
        match slice {
            &[red, green, blue] => Ok(Color {
                red: red.try_into()?,
                green: green.try_into()?,
                blue: blue.try_into()?,
            }),
            _ => Err("Invalid slice".into()),
        }
```

---

The need to use that match syntax is probably obvious for anyone familiar with Rust/slices, but for me Rust's auto-dereferencing is something that's meant I haven't really had to think about accounting for references much so far.

Prior to me finding the working approaches above, I tried this (which is missing the parentheses around the dereferencing):
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=832f13138c7edff6b6ba9cb5104924a5
```rust
        match slice {
            [red, green, blue] => Ok(Color {
                red: *red.try_into()?,
                green: *green.try_into()?,
                blue: *blue.try_into()?,
            }),
            _ => Err("Invalid slice".into()),
        }
```

...which gave this output, which also had me confused:

```
error[E0282]: type annotations needed
  --> src/main.rs:16:27
   |
16 |                 red: *red.try_into()?,
   |                       ----^^^^^^^^--
   |                       |   |
   |                       |   cannot infer type
   |                       this method call resolves to `Result<T, <Self as TryInto<T>>::Error>`
   |
   = note: type must be known at this point
```

And then I tried this (I was pretty much guessing and not thinking at this point):
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d0a17817fa45f2c9aa08b2ba29e9a4c8
```rust
        match slice {
            [&red, &green, &blue] => Ok(Color {
                red: red.try_into()?,
                green: green.try_into()?,
                blue: blue.try_into()?,
            }),
            _ => Err("Invalid slice".into()),
        }
```

...which gave this output:

```
error[E0308]: mismatched types
  --> src/main.rs:15:14
   |
14 |         match slice {
   |               ----- this expression has type `&[i16]`
15 |             [&red, &green, &blue] => Ok(Color {
   |              ^^^^
   |              |
   |              expected `i16`, found reference
   |              help: you can probably remove the explicit borrow: `red`
   |
   = note:   expected type `i16`
           found reference `&_`
...
```

...which is when the penny dropped about `slice` being `&[i16]` and to try `&[red, green, blue]`.