Repository: rust
Issue: Trait bound on associated type causes confusing compilation error
Labels: C-enhancement,A-diagnostics,A-associated-items,T-compiler

This code fails to compile:

```rust
pub trait Append<T> {
    type Appended;
}

pub trait Proc {
    type Item;
    type Tail;
    fn process_item<P>(&mut self, partial: P)
    where
        P: Append<Self::Item>,
        P::Appended: Append<Self::Tail>;
}

struct Read;

impl Proc for Read {
    type Item = i32;
    type Tail = i64;
    fn process_item<P>(&mut self, partial: P)
    where
        P: Append<Self::Item>,
        P::Appended: Append<Self::Tail>,
    {
        
    }
}
```

```
error[E0277]: the trait bound `P: Append<i32>` is not satisfied
  --> src/lib.rs:19:5
   |
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<Self::Item>,
22 | |         P::Appended: Append<Self::Tail>,
23 | |     {
24 | |         
25 | |     }
   | |_____^ the trait `Append<i32>` is not implemented for `P`
   |
   = help: consider adding a `where P: Append<i32>` bound
```

The error is confusing because `Self::Item` is `i32`. Furthermore, changing the bound on `P` to the suggested bound (setting aside the fact that this is a trait impl so imposing additional bounds isn't necessarily appropriate) yields an even more confusing error:

```
error[E0277]: the trait bound `P: Append<i32>` is not satisfied
  --> src/lib.rs:19:5
   |
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<i32>,
22 | |         P::Appended: Append<Self::Tail>,
23 | |     {
24 | |         
25 | |     }
   | |_____^ the trait `Append<i32>` is not implemented for `P`
   |
   = help: consider adding a `where P: Append<i32>` bound

error[E0276]: impl has stricter requirements than trait
  --> src/lib.rs:19:5
   |
8  | /     fn process_item<P>(&mut self, partial: P)
9  | |     where
10 | |         P: Append<Self::Item>,
11 | |         P::Appended: Append<Self::Tail>;
   | |________________________________________- definition of `process_item` from trait
...
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<i32>,
22 | |         P::Appended: Append<Self::Tail>,
23 | |     {
24 | |         
25 | |     }
   | |_____^ impl has extra requirement `P: Append<i32>`

error: aborting due to 2 previous errors
```

Adding an additional type parameter to the fn and using that as the bound on `P::Appended` appears to work fine, and i think it is semantically equivalent (although applying the bound directly to the associated type is cleaner IMO):

```rust
pub trait Append<T> {
    type Appended;
}

pub trait Proc {
    type Item;
    type Tail;
    fn process_item<P, T>(&mut self, partial: P)
    where
        P: Append<Self::Item, Appended = T>,
        T: Append<Self::Tail>;
}

struct Read;

impl Proc for Read {
    type Item = i32;
    type Tail = i64;
    fn process_item<P, T>(&mut self, partial: P)
    where
        P: Append<i32, Appended = T>,
        T: Append<Self::Tail>,
    {

    }
}
```

Should the original code compile?  If not, the error message (and suggested fix) is monumentally unhelpful. Otherwise, if it should compile, this looks like a compiler bug.