Rust Generics
You’ve already been using generics without necessarily naming them — Vec<i32> and Option<T> both use them. This page covers writing your own generic functions and structs.
The problem generics solve
Section titled “The problem generics solve”Say you want a function that returns the largest of a list of numbers, for both i32 and f64. Without generics, you’d write it twice:
fn largest_i32(numbers: &[i32]) -> i32 { let mut largest = numbers[0]; for &n in numbers { if n > largest { largest = n; } } largest}
fn largest_f64(numbers: &[f64]) -> f64 { let mut largest = numbers[0]; for &n in numbers { if n > largest { largest = n; } } largest}Same logic, copy-pasted for each type. Generics let you write it once.
A generic function
Section titled “A generic function”fn largest<T: PartialOrd + Copy>(numbers: &[T]) -> T { let mut largest = numbers[0]; for &n in numbers { if n > largest { largest = n; } } largest}
fn main() { let integers = [10, 25, 3, 47, 8]; let floats = [1.5, 2.8, 0.3];
println!("{}", largest(&integers)); println!("{}", largest(&floats));}Output:
472.8<T: PartialOrd + Copy> reads as “for any type T, as long as it can be compared (PartialOrd) and copied (Copy).” T is a placeholder — Rust generates a version of the function for whatever concrete type you actually call it with (i32, f64, and so on).
A generic struct
Section titled “A generic struct”Structs can be generic too:
struct Pair<T> { first: T, second: T,}
fn main() { let numbers = Pair { first: 5, second: 10 }; let words = Pair { first: "hello", second: "world" };
println!("{} {}", numbers.first, numbers.second); println!("{} {}", words.first, words.second);}Output:
5 10hello worldOne Pair<T> definition works for numbers, text, or any other type — numbers is a Pair<i32> and words is a Pair<&str>, but you only wrote the struct once.
Does this cost anything at runtime?
Section titled “Does this cost anything at runtime?”No. Rust generates a separate, specialized version of the function or struct for each concrete type you actually use (this is called monomorphization). By the time your program runs, there’s no generic code left — just ordinary, fully-typed functions, exactly as fast as if you’d hand-written each one.
- Generics let you write one function or struct that works with multiple types, instead of duplicating code.
<T>is a placeholder type; trait bounds (T: PartialOrd) restrict whatTis allowed to be.- Generic code is compiled into specialized versions per type — no runtime performance cost.