Rust Tutorial · Traits and Generics · Lesson 21 of 29

Rust Generics and Trait Bounds

Write functions and types that work with many types, constrained by trait bounds and where clauses.

Create a free account to save this page, take notes and track your progress. Sign in

Generic functions

fn largest<T: PartialOrd>(items: &[T]) -> &T works for any T that can be compared. The bound says what T must support; the compiler generates specialised code for each type used (zero runtime cost).

Generic functions, structs and impl Trait
use std::fmt::Display;

fn largest<T: PartialOrd>(items: &[T]) -> &T {
    let mut best = &items[0];
    for item in items {
        if item > best { best = item; }
    }
    best
}

struct Pair<T> { a: T, b: T }

impl<T> Pair<T>
where
    T: PartialOrd + Display,
{
    fn show_bigger(&self) -> String {
        if self.a >= self.b { format!("{}", self.a) } else { format!("{}", self.b) }
    }
}

fn evens(limit: u32) -> impl Iterator<Item = u32> {
    (0..limit).filter(|n| n % 2 == 0)
}

fn main() {
    println!("{}", largest(&[3, 9, 4]));
    println!("{}", largest(&["pear", "apple", "zucchini"]));
    println!("{}", Pair { a: 2.5, b: 1.0 }.show_bigger());
    println!("{:?}", evens(10).collect::<Vec<_>>());
}

Output

9
zucchini
2.5
[0, 2, 4, 6, 8]

Run this on your computer — see “Get Started” for setup.

impl Trait

fn print_all(items: impl IntoIterator<Item = impl Display>) is shorthand for a generic parameter, and -> impl Iterator<Item = u32> returns some type implementing a trait without naming it.

Test yourself

What does the bound T: PartialOrd mean?

  1. T must be a number
  2. T must support comparison with < and >
  3. T is optional
  4. T is a reference
Show answer

Answer: T must support comparison with < and >

Was this page helpful?