Traits

Multiple Trait Bounds

A multiple trait bound (T: TraitA + TraitB) requires a generic type parameter to implement every trait in a +-separated list simultaneously.

Combining Traits with the + Operator

Inside a function or impl block where T: TraitA + TraitB is declared, values of type T can call methods from both TraitA and TraitB:

use std::fmt::{Debug, Display};

fn audit_And_clone<T: Display + Debug + Clone>(item: &T) -> T {
    println!("Display view: {item}");
    println!("Debug view:   {item:?}");
    item.clone()
}

fn main() {
    let original = String::from("release-v2.1");
    let copy = audit_And_clone(&original);
    println!("Cloned copy:  {copy}");
}
Display view: release-v2.1
Debug view:   "release-v2.1"
Cloned copy:  release-v2.1

Multiple Bounds Across Multiple Type Parameters

When a signature has more than one generic parameter and each carries multiple trait bounds, you can write them inline or move them into a where clause:

use std::fmt::Display;
use std::hash::Hash;

// Inline syntax:
fn describe_entry_inline<K: Display + Eq + Hash, V: Display + Default>(key: K, value: Option<V>) {
    let resolved = value.unwrap_or_default();
    println!("{key} => {resolved}");
}

// Equivalent `where` clause syntax:
fn describe_entry_where<K, V>(key: K, value: Option<V>)
where
    K: Display + Eq + Hash,
    V: Display + Default,
{
    let resolved = value.unwrap_or_default();
    println!("{key} => {resolved}");
}

fn main() {
    describe_entry_inline("timeout_sec", Some(30_u32));
    describe_entry_where("retries", None::<u32>);
}
timeout_sec => 30
retries => 0

Combining Trait Bounds with Lifetime Bounds

The + syntax also combines trait bounds with lifetime bounds such as 'static or 'a. For example, T: Send + Sync + 'static requires T to be safe to transfer and share across threads and free of any non-'static borrowed references:

use std::fmt::Debug;
use std::thread;

fn spawn_printer<T>(payload: T) -> thread::JoinHandle<()>
where
    T: Debug + Send + 'static,
{
    thread::spawn(move || {
        println!("Worker thread received: {payload:?}");
    })
}

fn main() {
    let handle = spawn_printer(vec![10, 20, 30]);
    handle.join().unwrap();
}
Worker thread received: [10, 20, 30]

Partial Satisfaction Fails at Compile Time

A concrete type passed to T: TraitA + TraitB must implement all listed traits. If a type implements TraitA (Debug) but not TraitB (Clone), the compiler reports specifically which missing trait caused the failure:

// ❌ does not compile
use std::fmt::Debug;

#[derive(Debug)]
struct NonCloneToken(u64);

fn duplicate_debug<T: Debug + Clone>(val: &T) -> T {
    println!("{val:?}");
    val.clone()
}

fn main() {
    let token = NonCloneToken(99);
    let _copy = duplicate_debug(&token);
}
error[E0277]: the trait bound `NonCloneToken: Clone` is not satisfied
  --> src/main.rs:14:33
   |
14 |     let _copy = duplicate_debug(&token);
   |                 --------------- ^^^^^^ the trait `Clone` is not implemented for `NonCloneToken`
   |                 |
   |                 required by a bound introduced by this call
   |
note: required by a bound in `duplicate_debug`
  --> src/main.rs:7:31
   |
7  | fn duplicate_debug<T: Debug + Clone>(val: &T) -> T {
   |                               ^^^^^ required by this bound in `duplicate_debug`