Repository: rust
Issue: Associated type bounds are not equivalent to de-sugared `where` clauses for supertraits and nested associated types
Labels: A-trait-system,T-types

I am not sure if this is a bug or a documentation issue.

The Rust Reference [states](https://doc.rust-lang.org/reference/trait-bounds.html):
> - In trait declarations as supertraits: `trait Circle: Shape {}` is equivalent to `trait Circle where Self: Shape {}`
> - In trait declarations as bounds on associated types: `trait A { type B: Copy; }` is equivalent to `trait A where Self::B: Copy { type B; }`

This matches the [associated type bounds RFC](https://github.com/rust-lang/rfcs/blob/master/text/2289-associated-type-bounds.md#reference-level-explanation):
> - The surface syntax `T: Trait<AssociatedType: Bounds>` should desugar to a pair of bounds: `T: Trait` and `<T as Trait>::AssociatedType: Bounds`.
> - The new syntax does not introduce any new semantics.

The [stabilization PR](https://github.com/rust-lang/rust/pull/122055#issue-2170532454) says *almost* the same thing, but with a subtle difference:
> - […] `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`.
> - Supertraits - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is **almost** equivalent to breaking up the bound into two (or more) `where` clauses; however, **the bound on the associated item is implied whenever the trait is used**. See [Should associated type bounds on supertraits be implied? #112573](https://github.com/rust-lang/rust/issues/112573)/[Make associated type bounds in supertrait position implied #112629](https://github.com/rust-lang/rust/pull/112629).
> - Associated type item bounds - This allows constraining the nested rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`.

(Emphasis mine.)

However, the PR linked in that second bullet, [Make associated type bounds in supertrait position implied](https://github.com/rust-lang/rust/pull/112629), implies that this `where` clause implies the same bounds as the `B<Assoc: C>` syntax:
> `trait A: B<Assoc: C> {}` should be able to imply both `Self: B` and `<Self as B>::Assoc: C`.

For normal associated types, this is definitely the case, but for bounds on associated types of supertraits, and bounds on associated types of associated types, these two forms are demonstrably *not* equivalent:

This compiles:
```rust
// A trait which has bounds on a nested associated type,
// using shorthand associated type bounds syntax.
// Associated type bounds ARE implied elsewhere.
pub trait NestedSugar
{
    // Sufficient.
    type Output: Iterator<Item: Clone>;
    fn make() -> Self::Output;
}

pub fn nested_sugar<T>() -> <T::Output as Iterator>::Item
where
    T: NestedSugar,
    // `No <T::Output as Iterator>::Item: Clone` required.
{
    T::make().next().unwrap().clone()
}
```

And this compiles:
```rust
// Supertrait with bounds on the associated type of the subtrait,
// using shorthand associated type bounds syntax.
// Supertrait associated type bounds ARE implied elsewhere.
pub trait SuperSugar
where
    Self: Iterator<Item: PartialEq>,
{
    fn super_next_sugar(&self) -> <Self as Iterator>::Item;
}

pub fn take_sugar<I>(iter: I) -> bool
where
    I: SuperSugar,
    // No `<I as Iterator>::Item: PartialEq` required.
{
    let first = iter.super_next_sugar();
    let second = iter.super_next_sugar();
    first == second
}
```

But this does not compile:
```rust
// A trait which has bounds on a nested associated type,
// using a where clause.
// The associated type bounds are NOT implied elsewhere.
pub trait NestedWhere
where
    Self::Output: Iterator,
    // Not sufficient.
    <Self::Output as Iterator>::Item: Clone,
{
    type Output;
    // GAT-ish syntax is also not sufficient:
    //type Output: Iterator where <Self::Output as Iterator>::Item: Clone;
    
    fn make() -> Self::Output;
}

pub fn nested_where<T>() -> <T::Output as Iterator>::Item
where
    T: NestedWhere,
    // Required. Does not compile without this line:
    //<T::Output as Iterator>::Item: Clone,
    // error[E0277]: the trait bound `<<T as NestedWhere>::Output as Iterator>::Item: Clone` is not satisfied
{
    T::make().next().unwrap().clone()
}
```

Nor does this:
```rust
// Supertrait with bounds on the associated type of the subtrait,
// using a where clause.
// Associated type bounds are NOT implied elsewhere.
pub trait SuperWhere
where
    Self: Iterator,
    // Not sufficient.
    <Self as Iterator>::Item: PartialEq,
{
    fn super_next_where(&self) -> <Self as Iterator>::Item;
}

pub fn take_where<I>(iter: I) -> bool
where
    I: SuperWhere,
    // Required. Does not compile without this line:
    //<I as Iterator>::Item: PartialEq,
    // error[E0277]: can't compare `<I as Iterator>::Item` with `<I as Iterator>::Item`
    // help: the trait `PartialEq` is not implemented for `<I as Iterator>::Item`
{
    let first = iter.super_next_where();
    let second = iter.super_next_where();
    first == second
}
```

---

## Playground

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=faec69dd74703073da0a6183cceb9afd

## See also

- [rust-lang/rust#58231: Trait bounds on associated type causes confusing compilation error](https://github.com/rust-lang/rust/issues/58231)
- [rust-lang/rust#57905: Compiler unable to apply trait bound](https://github.com/rust-lang/rust/issues/57905)
- [rust-lang/rust#20671: where clauses are only elaborated for supertraits, and not other things](https://github.com/rust-lang/rust/issues/20671)
- [rust-lang/rust#103387: `where` on `trait` declaration should be provided when the trait is an input bound, but is instead a requirement](https://github.com/rust-lang/rust/issues/103387)

All of those issues talk about type bounds not being implied in one case or another, but as far as I can tell there is no issue about the *discrepancy* of implied bounds between these two syntaxes. And again I am not sure if this is a bug or a documentation (and possibly diagnostics) issue.