Associated type's bounds are not propagated under cerain circumstances

I encountered this situation (playground) in a real program:

trait ItemSource {
    type Item;
}

trait ItemSink<T> {}

trait Outer<T>: ItemSource + ItemSink<<Self as ItemSource>::Item> {
    type Inner: Inner<Self::Item>;
}

trait Inner<T> {}

fn f<I, T: Outer<(), Item = I>>(_: I, _: T) {}

This gives me the following error message:

error[E0277]: the trait bound `<T as Outer<()>>::Inner: Inner<I>` is not satisfied
  --> src/lib.rs:13:12
   |
7  | trait Outer<T>: ItemSource + ItemSink<<Self as ItemSource>::Item> {
   | ----------------------------------------------------------------- required by `Outer`
...
13 | fn f<I, T: Outer<(), Item = I>>(_: I, _: T) {}
   |            ^^^^^^^^^^^^^^^^^^^             - help: consider further restricting the associated type: `where <T as Outer<()>>::Inner: Inner<I>`
   |            |
   |            the trait `Inner<I>` is not implemented for `<T as Outer<()>>::Inner`

Note, however, that if I change Inner's type bound to Inner<T>, i.e. to a type parameter instead of an associated type, the error goes away, so it makes me think that this is not intentional. Is this a compiler bug?

Did you try the suggestion in the error message? Works for me:

fn f<I, T: Outer<(), Item = I>>(_: I, _: T)
where
    <T as Outer<()>>::Inner: Inner<I>
{}

It works, but it my real use case it means adding a ton of where clauses which make the code unreadable. It seems like something that the compiler should be doing on its own, that's why I'm asking if it's intentional.

I think this is long-standing issue #20671

1 Like