Generics

Generic Associated Functions

A generic associated function is a function defined inside an impl block that does not take a self, &self, or &mut self receiver and operates on type parameters from the enclosing impl<T> block, its own fn<U> parameter list, or both.

Constructors on Generic Types

The most common generic associated functions are constructors such as Vec::new(), Vec::with_capacity(), or custom Type::new() functions:

#[derive(Debug)]
struct BoundedQueue<T> {
    capacity: usize,
    items: Vec<T>,
}

impl<T> BoundedQueue<T> {
    fn with_capacity(capacity: usize) -> Self {
        Self {
            capacity,
            items: Vec::with_capacity(capacity),
        }
    }

    fn push(&mut self, item: T) -> Result<(), T> {
        if self.items.len() >= self.capacity {
            Err(item)
        } else {
            self.items.push(item);
            Ok(())
        }
    }
}

fn main() {
    // T is inferred as &str from the subsequent push("task-1") call:
    let mut queue = BoundedQueue::with_capacity(2);
    queue.push("task-1").unwrap();
    queue.push("task-2").unwrap();

    println!("Queue: {queue:?}");
    println!("Overflow push: {:?}", queue.push("task-3"));
}
Queue: BoundedQueue { capacity: 2, items: ["task-1", "task-2"] }
Overflow push: Err("task-3")

Calling Generic Associated Functions with Turbofish

When you want to fix the concrete type T at the point where the associated function is called, place the turbofish (::<T>) on the type segment before ::function_name:

#[derive(Debug)]
struct Registry<T> {
    entries: Vec<T>,
}

impl<T> Registry<T> {
    fn empty() -> Self {
        Self {
            entries: Vec::new(),
        }
    }
}

fn main() {
    // Turbofish on the type segment:
    let reg = Registry::<u64>::empty();
    println!("Entries count: {}", reg.entries.len());
}
Entries count: 0

Placing the type arguments of the struct after the associated function name (Registry::empty::<u64>()) when empty itself declares zero function-level type parameters triggers error E0107:

// ❌ does not compile
struct Registry<T> {
    entries: Vec<T>,
}

impl<T> Registry<T> {
    fn empty() -> Self {
        Self {
            entries: Vec::new(),
        }
    }
}

fn main() {
    let _reg = Registry::empty::<u64>();
}
error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied
  --> src/main.rs:15:26
   |
15 |     let _reg = Registry::empty::<u64>();
   |                          ^^^^^------- help: remove the unnecessary generics
   |                          |
   |                          expected 0 generic arguments

Associated Functions with Independent Type Parameters

An associated function can also introduce its own type parameters (fn from_iter<I>(...) or fn convert_from<U>(...)) separate from the struct's type parameter T:

#[derive(Debug)]
struct Summary<T> {
    first: Option<T>,
    count: usize,
}

impl<T> Summary<T> {
    fn from_converted<U, I>(iter: I) -> Self
    where
        I: IntoIterator<Item = U>,
        U: Into<T>,
    {
        let mut iter = iter.into_iter();
        let first = iter.next().map(Into::into);
        let count = usize::from(first.is_some()) + iter.count();
        Self { first, count }
    }
}

fn main() {
    // T = String (on Summary<T>), U = &str, I = [&str; 3] (on from_converted):
    let report = Summary::<String>::from_converted(["init", "run", "stop"]);
    println!("{report:?}");
}
Summary { first: Some("init"), count: 3 }
Call Syntax Binds Type Parameter On
Summary::<String>::from_converted(...) The impl<T> Summary<T> block (T = String)
Summary::from_converted::<&str, _>(...) The fn from_converted<U, I> signature (U = &str)
Summary::<String>::from_converted::<&str, _>(...) Both the struct T and the associated function U