Associated Types and Advanced Traits

Generic Traits

A generic trait is a trait parameterized over one or more type parameters (trait Name<T>), allowing a single type to implement the same trait multiple times for different type arguments.

Defining and Implementing a Generic Trait

When a trait has a type parameter T, each impl Trait<ConcreteType> for MyType block is a distinct implementation:

trait ConvertTo<Output> {
    fn convert(&self) -> Output;
}

struct TemperatureCelsius(f64);

impl ConvertTo<f64> for TemperatureCelsius {
    fn convert(&self) -> f64 {
        self.0
    }
}

impl ConvertTo<String> for TemperatureCelsius {
    fn convert(&self) -> String {
        format!("{:.1} °C", self.0)
    }
}

fn main() {
    let temp = TemperatureCelsius(25.0);

    // Type annotations select which implementation of ConvertTo<Output> is called:
    let raw: f64 = temp.convert();
    let label: String = temp.convert();

    println!("raw = {raw}, label = {label}");
}
raw = 25, label = 25.0 °C

Generic Blanket Implementations

A generic trait can also be implemented generically for a family of types by declaring type parameters on the impl<...> header itself:

trait SummarizeFrom<Source> {
    fn summarize(src: &Source) -> String;
}

struct Report;

// Implements SummarizeFrom<&[T]> for Report for ANY T that implements Debug:
impl<T: std::fmt::Debug> SummarizeFrom<[T]> for Report {
    fn summarize(src: &[T]) -> String {
        format!("{} items: {:?}", src.len(), src)
    }
}

fn main() {
    let numbers = [10, 20, 30];
    let words = ["rust", "traits"];

    println!("{}", Report::summarize(&numbers[..]));
    println!("{}", Report::summarize(&words[..]));
}
3 items: [10, 20, 30]
2 items: ["rust", "traits"]

Standard Library Generic Traits

Generic Trait Type Parameter Role Why It Uses a Generic Parameter
From<T> / Into<T> Source or target type T One type can convert from/into many different types (String: From<&str>, String: From<char>)
AsRef<T> / AsMut<T> Borrowed view target T String can be borrowed as AsRef<str>, AsRef<[u8]>, and AsRef<Path> simultaneously
PartialEq<Rhs> Right-hand operand type Allows comparing String == &str and String == String
Index<Idx> Index key type Idx Vec<T> implements Index<usize>, Index<Range<usize>>, and Index<RangeFull>