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 |