Repository: rust
Issue: Improvements to error messages from nested indexing
Labels: C-enhancement,A-diagnostics,A-trait-system,T-compiler,A-suggestion-diagnostics,D-confusing,D-invalid-suggestion

<!--
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.
-->

I tried this code:

```rust
struct Board(Vec<Vec<String>>);

impl<I, J> Index<(I, J)> for Board {
    type Output = String;

    fn index(&self, index: (I, J)) -> &Self::Output {
        self.0[index.1][index.0]
    }
}
```

This fails, and `rustc` suggests adding constraints:

```
error[E0277]: the type `[std::vec::Vec<std::string::String>]` cannot be indexed by `J`
  --> src/lib.rs:24:10
   |
24 |         &self.0[index.1][index.0]
   |          ^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
   |
   = note: required because of the requirements on the impl of `std::ops::Index<J>` for `std::vec::Vec<std::vec::Vec<std::string::String>>`
help: consider restricting type parameter `J`
   |
20 | impl<I, J: std::slice::SliceIndex<[std::vec::Vec<std::string::String>]>> Index<(I, J)> for Board {
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

Applying the suggested changes:

```rust
struct Board(Vec<Vec<String>>);

impl<I: SliceIndex<[String]>, J: SliceIndex<[Vec<String>]>> Index<(I, J)> for Board {
    type Output = String;

    fn index(&self, index: (I, J)) -> &Self::Output {
        self.0[index.1][index.0]
    }
}
```

`rustc` produced the following error, which fails to indicate that what's needed is specifying the output type. (Further, `J` is mentioned, which is not relevant to the line being pointed, but rather the `Index` `impl`.)

```
error[E0608]: cannot index into a value of type `<J as std::slice::SliceIndex<[std::vec::Vec<std::string::String>]>>::Output`
  --> src/lib.rs:24:9
   |
24 |         self.0[index.1][index.0]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^
```

The correct code is the following:

```rust
struct Board(Vec<Vec<String>>);

impl<
        I: SliceIndex<[String], Output = String>,
        J: SliceIndex<[Vec<String>], Output = Vec<String>>,
    > Index<(I, J)> for Board
{
    type Output = String;

    fn index(&self, index: (I, J)) -> &Self::Output {
        &self.0[index.1][index.0]
    }
}
```

As a side note, the following (incorrect) fix was proposed:

```rust
struct Board(Vec<Vec<String>>);

impl<
        I: SliceIndex<[String], Output = String>,
        J: SliceIndex<[Vec<String>], Output = [String]>,
    > Index<(I, J)> for Board
{
    type Output = String;

    fn index(&self, index: (I, J)) -> &Self::Output {
        &self.0[index.1][index.0]
    }
}
```

As expected, this compiles, and fails when trying to use the operator:

```
error[E0271]: type mismatch resolving `<usize as std::slice::SliceIndex<[std::vec::Vec<std::string::String>]>>::Output == [std::string::String]`
   --> src/lib.rs:271:23
    |
271 |         while step >= self.board[coords].len() {
    |                       ^^^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found slice
    |
    = note: expected type `std::vec::Vec<std::string::String>`
              found slice `[std::string::String]`
    = note: required because of the requirements on the impl of `std::ops::Index<(usize, usize)>` for `Board`
```

However, the line being pointed at shows the usage site, when the types being discussed are rather relevant to the `impl` block. This might be improvable as well.

### Meta
<!--
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.
-->

`rustc --version --verbose`:

```
issotm@sheik-kitty ~% rustc --version --verbose
rustc 1.47.0 (18bf6b4f0 2020-10-07)
binary: rustc
commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
commit-date: 2020-10-07
host: x86_64-unknown-linux-gnu
release: 1.47.0
LLVM version: 11.0
```