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).