Use trait bounds to constrain generic types so they implement specific traits, ensuring the code can call those trait's methods. Place the bound after the generic type with a colon in function signatures or after the impl block for structs.
fn print_largest<T: PartialOrd + std::fmt::Display>(list: &[T]) {
let largest = list.iter().max().unwrap();
println!("The largest is {largest}");
}
For multiple bounds, separate them with a plus sign (+). Use the where clause for complex constraints or when the signature becomes too long.
fn print_largest<T>(list: &[T])
where
T: PartialOrd + std::fmt::Display,
{
let largest = list.iter().max().unwrap();
println!("The largest is {largest}");
}