A generic type parameter, written in angle brackets like <T>, lets a function, struct, or enum work across many concrete types without duplicating code. Rust compiles generics via monomorphization: for every concrete type actually used, the compiler generates a fully specialized copy of the code at compile time — meaning generic code runs exactly as fast as if you had hand-written a version for each type, with zero runtime dispatch overhead.
A generic function
The trait bound T: PartialOrd restricts T to types that support comparison operators — without it, the compiler would not know whether > is even valid for an arbitrary T.
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
let mut largest = list[0];
for &item in list {
if item > largest {
largest = item;
}
}
largest
}
println!("{}", largest(&[10, 25, 3, 47])); // 47, T inferred as i32
println!("{}", largest(&[1.2, 5.6, 3.1])); // 5.6, T inferred as f64Generic structs
A struct can be generic over one or more type parameters, letting the same struct definition hold any type without duplication.
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn new(x: T, y: T) -> Point<T> {
Point { x, y }
}
}
let int_point = Point::new(5, 10); // Point<i32>
let float_point = Point::new(1.5, 2.5); // Point<f64>, a DIFFERENT concrete typeMonomorphization: zero-cost, at the price of binary size
Because the compiler generates a separate copy of the generic code for every concrete type actually used, using the same generic function or struct with many different types can increase the compiled binary's size (sometimes called "code bloat") — the tradeoff for having no runtime dispatch or boxing overhead the way type-erased generics in other languages often require.