A trait bound says what a type must be able to do before it can be used somewhere. Think of it as a qualification: a function need not care which type it receives, as long as that type implements the required trait. A trait can even have no methods and still serve as a qualification. section 7.1.3
Require two abilities
`fn print_maximum<T: PartialOrd + Display>(one: T, two: T)` accepts two values of the same type `T`. `PartialOrd` permits the comparison; `Display` permits printing the result with `{}`. The `+` means both traits are required. The bounds can also follow `where` instead of appearing beside `T`. section 12.2.1 section 7.1.3
A bound can also appear on a trait: `trait MonsterBehavior: Debug` requires every type implementing `MonsterBehavior` to implement `Debug`. That lets a default method print `self` with `{:?}`, even though the trait does not know the concrete type. A method can separately accept `T: MonsterBehavior` and call the abilities that trait provides. section 7.1.2
use std::fmt::Display;
fn print_maximum<T: PartialOrd + Display>(one: T, two: T) {
let higher = if one > two { one } else { two };
println!("{higher} is higher.");
}
fn main() {
print_maximum(8, 10);
}
The complete `print_maximum` example shows the shared type `T`, its two bounds, and a call using numbers. section 12.2.1
Compiler errors can reveal an important distinction. Replacing each `T` in that comparison with a separate `impl PartialOrd + Display` does not say the arguments have the same type, so comparing them fails. Keep the named `T` when arguments must share a type; use `impl Trait` when that shared-type relationship is not needed. section 12.2.1

