Understanding associated types for traits in Rust

Common traits such as Add, Mul have associated types.

You can find this in the declaration of these traits:

Both use Output as their associated type.

This is an auxilary type which can then be used in declarations.

pub struct Vec3<T> {
    x: T,
    y: T,
    z: T,
}

impl <T: Add<Output = T>> Add for Vec3<T> {
    type Output = Self; // Bind auxilary type
    fn add(self, other: Vec3< T >) -> Self::Output {
                                      // Use it for the return value
        Self {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

It has the advantage of providing a uniform interface and flexibility (by choosing what to bind to the type).

The confusing part for me was seeing two places in which it seemed to be bound:

impl <T: Add<Output = T>> Add for Vec3<T> {
           // ^
           // Bound here (1)

      // Bound here (2)
      // v
    type Output = Self; // Bind auxilary type
    fn add(self, other: Vec3< T >) -> Self::Output {
        Self {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

After doing some digging, for (1), Output = T is scoped to the trait binding of T. In plain english, we are saying T implements the trait Add which has defined Output type as T.

Hence because this is scoped to (1), the binding does not overlap with (2).