Keyword as and where

When reading the interface of join method for vec, i got a small question.

// https://doc.rust-lang.org/src/alloc/slice.rs.html#573-575
    #[rustc_allow_incoherent_impl]
    #[stable(feature = "rename_connect_to_join", since = "1.3.0")]
    pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
    where
        Self: Join<Separator>,
    {
        Join::join(self, sep)
    }

The point i am quite confused is that the return type of the method is <Self as Join<Separator>>::Output. IMHO, the return can just be Join<Separator>::Output because in the following where clause there is already a bind about Self and Join i.e. Self: Join<Separator>.

Can anyone help to explain this ?

1 Like

No, you certainly can't write Join<Separator>::Output because Join<Separator> is a trait. Sure, we know that Self implements that trait, but there are also other things that implement it. The colon does not mean equality — it means "left-hand-side implements right-hand-side".

That said, writing Self::Output would be ok here. (Unless Self implements multiple different traits with an associated type called Output, as it would become ambiguous if there are several.)

5 Likes

(Same response as @alice with different wording.)


Trait::Associated is considered ambiguous because in addition to <Self as Trait>::Associated, there are also other known candidates (<SomethingElse as Trait>::Associated).

The Self: Trait bound doesn't erase the knowledge that SomethingElse: Trait.

Self::Output would work in this case though. But it's still technically less robust as it would become ambiguous in the face of

impl<T: ?Sized> EverythingExt for T {
    type Output = ();
}
4 Likes