Where Clauses
where clause is a tidy list, off to the side, of all the rules a function's types have to follow.In this page:
Basic where Clause
A where clause lists trait bounds separately after the function signature, keeping the parameter list itself clean and easy to scan.
Example: Basic where Clause
use std::fmt::Display;
fn describe<T>(item: T) -> String
where
T: Display,
{
format!("Item: {}", item)
}
fn main() {
println!("{}", describe(99));
}
Login to try C/C++/Java/PHP code in the editor
Multiple Bounds in a where Clause
When a function has several generic parameters each needing their own bounds, a where clause lists them all clearly, one per line, instead of a cramped inline list.
Example: Multiple Bounds in a where Clause
use std::fmt::{Debug, Display};
fn compare<T, U>(a: T, b: U) -> String
where
T: Display,
U: Debug,
{
format!("{} vs {:?}", a, b)
}
fn main() {
println!("{}", compare(5, vec![1, 2]));
}
Login to try C/C++/Java/PHP code in the editor
Bounding a Generic Container Type
where clauses can express bounds on more complex generic types, such as requiring the elements inside a Vec<T> to implement a particular trait.
Example: Bounding a Generic Container Type
fn print_all<T>(items: Vec<T>)
where
T: std::fmt::Display,
{
for item in items {
println!("{}", item);
}
}
fn main() {
print_all(vec![1, 2, 3]);
}
Login to try C/C++/Java/PHP code in the editor
where Clauses vs Inline Bounds
Inline bounds and where clauses express exactly the same constraints -- the choice is purely about readability, with where clauses generally preferred once bounds become numerous or complex.
Example: where Clauses vs Inline Bounds
fn largest<T: PartialOrd + Copy>(items: &[T]) -> T
where
T: std::fmt::Debug,
{
let mut largest = items[0];
for &item in items {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let numbers = [3, 7, 2, 9, 4];
println!("{:?}", largest(&numbers));
}
Login to try C/C++/Java/PHP code in the editor
- Cramming many trait bounds directly into a generic parameter list, making the function signature hard to read, instead of using a
whereclause. - Assuming
whereclauses can express something inline bounds cannot -- they are equivalent in power, just more readable for complex cases. - Forgetting a
whereclause still needs each bound to be satisfiable by the actual types used when the function is called.
whereclauses move trait bounds out of the angle brackets into a dedicated section after the function signature.- They are functionally equivalent to inline bounds, but greatly improve readability for functions with multiple constrained parameters.
whereclauses can express bounds on complex types, such asVec<T>needingT: Clone.- Idiomatic Rust prefers
whereclauses once a function has more than one or two simple bounds.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: