A function that takes an `i32` cannot take a different type in its place. Generics let one function work with multiple concrete types instead of making you write a separate function for each type. Rust still uses concrete types: it turns generic functions into concrete ones at compile time, with no extra runtime work. section 5.1 section 5.3
fn return_item<T>(item: T) -> T {
println!("Here is your item.");
item
}
fn main() {
let item = return_item(5);
}
In `fn return_item<T>(item: T) -> T`, the angle brackets declare `T` as a type parameter. The same `T` on the input and output says the function returns the type it receives. The call with `5` supplies a concrete type. section 5.1
The name `T` is a convention, not a special word; you could choose another name. But you must declare it in angle brackets after the function name. Without that declaration, Rust looks for a concrete type with that name and reports that it cannot find it. section 5.1
A generic type cannot automatically perform every operation. For example, formatting a value with `{:?}` fails if Rust cannot tell whether its type implements `Debug`. A trait bound supplies that requirement: `fn print_item<T: Debug>(item: T)`. Adding bounds lets the function do more, but admits fewer types. section 5.1 section 5.3
use std::fmt::Debug; #1
fn print_item<T: Debug>(item: T) { #2
println!("Here is your item: {item:?}");
}
fn main() {
print_item(5);
}
The `Debug` bound makes the formatting operation valid for any accepted `T`. section 5.1
Use separate parameters such as `T` and `U` when inputs may have different types. Each can have its own bounds; `+` combines bounds, and a `where` clause moves them below the signature when it gets crowded. Reusing `T` for two inputs instead says they have the same type. section 5.1 section 12.2.1
When one shared type matters
A function that compares and prints two values can use `fn print_maximum<T: PartialOrd + Display>(one: T, two: T)`. `PartialOrd` supports the comparison, `Display` supports printing, and the repeated `T` ties the inputs to one type. Writing `impl PartialOrd + Display` separately for each input does not establish that relationship. section 12.2.1
The same pattern appears in iterator methods that accept closures: a parameter such as `F` has a bound describing the closure it accepts. In a blanket trait implementation, `impl<T>` can cover every type when `T` has no bounds, or only types satisfying stated bounds. section 12.1 section 17.6



















