11.5 Advanced Generics

Generics in Rust provide powerful ways to write reusable, performance-oriented code. This section covers some advanced features—associated types in traits, const generics, and how monomorphization influences performance.

11.5.1 Associated Types in Traits

We’ve seen that Iterator uses an associated type, type Item, to indicate what each iteration yields. This strategy prevents you from having to write:

trait Iterator<T> {
    fn next(&mut self) -> Option<T>;
}

Instead, an associated type Item keeps the trait interface cleaner:

#![allow(unused)]
fn main() {
trait Container {
    type Item;
    fn contains(&self, item: &Self::Item) -> bool;
}

struct NumberContainer {
    numbers: Vec<i32>,
}

impl Container for NumberContainer {
    type Item = i32;

    fn contains(&self, item: &i32) -> bool {
        self.numbers.contains(item)
    }
}
}

11.5.2 Const Generics

Const generics let you specify constants (such as array sizes) as part of your generic parameters:

struct ArrayWrapper<T, const N: usize> {
    elements: [T; N],
}

fn main() {
    let array = ArrayWrapper { elements: [0; 5] };
    println!("Array length: {}", array.elements.len());
}

11.5.3 Generics and Performance

Rust’s monomorphization process duplicates generic functions or types for each concrete type used, leading to specialized, optimized machine code. As in C++ templates, this often means:

  • Zero-Cost Abstractions: The compiled program pays no runtime penalty for using generics.
  • Potential Code Size Increase: Widespread usage of generics with many different concrete types can inflate the final binary.