RustArena

Rust error E0277: the trait bound is not satisfied

What Rust's E0277 error means (a type doesn't implement a required trait) and how to fix its most common forms: Display, Ord, Send, ? and collect.

E0277 means some code requires a type to implement a trait, and it doesn't. It's the error behind many differently worded messages, so it helps to recognize the pattern: which type, which trait, and who requires it.

The classic form names the trait directly:

#[derive(Debug)]
struct Item {
    name: String,
}

fn duplicate<T: Clone>(x: &T) -> T {
    x.clone()
}

fn main() {
    let sword = Item { name: String::from("sword") };
    println!("{:?}", duplicate(&sword).name);
}
error[E0277]: the trait bound `Item: Clone` is not satisfied

duplicate requires T: Clone, and Item doesn't implement Clone. Fix: #[derive(Debug, Clone)].

The common forms, and their fixes

Message Cause Fix
`Point` doesn't implement `std::fmt::Display` {} on your type use {:?} or implement Display
`Point` doesn't implement `Debug` {:?} without derive #[derive(Debug)]
the trait bound `{float}: Ord` is not satisfied sort(), max(), BTreeMap key on floats sort_by(|a, b| a.total_cmp(b))
`T` doesn't implement `std::fmt::Display` generic function uses a trait it didn't ask for add the bound: T: Display
cannot add `i64` to `i32` mixed number types convert one side
the type `[i32]` cannot be indexed by `i32` index isn't usize v[i as usize] or use usize
the `?` operator can only be used in a function that returns `Result` or `Option` ? in main or a () function return a Result
`?` couldn't convert the error to `MyError` no From impl for the error implement From, or map_err
a value of type `Vec<i32>` cannot be built from an iterator over elements of type `&i32` collecting references .copied() or .cloned() before collect
`Rc<i32>` cannot be sent between threads safely Rc moved into a thread use Arc

Generic code: add the bound

Inside a generic function you may only use what the bounds promise:

fn print_all<T>(items: &[T]) {
    for item in items {
        println!("{item}");
    }
}

fn main() {
    print_all(&[1, 2, 3]);
}
error[E0277]: `T` doesn't implement `std::fmt::Display`

rustc suggests the fix: "consider restricting type parameter T with trait Display", meaning fn print_all<T: std::fmt::Display>(items: &[T]).

Sorting floats

fn main() {
    let mut temps = vec![21.5, 19.0, 23.25];
    temps.sort();
    println!("{temps:?}");
}
error[E0277]: the trait bound `{float}: Ord` is not satisfied

sort needs a total order (Ord), and floats only have a partial one because NaN isn't comparable. temps.sort_by(|a, b| a.total_cmp(b)) sorts with IEEE 754's total order.

How to read a long E0277

  1. Find the type and trait in the first line.
  2. Look for required by a bound in ...: it names the function or impl that demands the trait.
  3. Look at the help: lines: rustc lists types that do implement the trait, and often the exact derive or bound to add.
  4. If the type is foreign and the trait is foreign (say Display for Vec<T>), the orphan rule stops you implementing it directly; wrap the type in a newtype.

Example

use std::fmt::Display;

#[derive(Debug, Clone, PartialEq)]
struct Item {
    name: String,
    price: f64,
}

fn duplicate<T: Clone>(x: &T) -> T {
    x.clone()
}

fn print_all<T: Display>(items: &[T]) {
    let parts: Vec<String> = items.iter().map(|i| i.to_string()).collect();
    println!("{}", parts.join(" | "));
}

fn main() {
    let sword = Item { name: String::from("sword"), price: 12.5 };
    let copy = duplicate(&sword);
    println!("{copy:?} equal: {}", copy == sword);

    print_all(&[1, 2, 3]);
    print_all(&["a", "b"]);

    let mut temps = vec![21.5, 19.0, 23.25];
    temps.sort_by(|a: &f64, b| a.total_cmp(b));
    println!("{temps:?}");

    let mut items = vec![copy, Item { name: String::from("potion"), price: 3.0 }];
    items.sort_by(|a, b| a.price.total_cmp(&b.price));
    println!("cheapest: {}", items[0].name);

    let v = vec![1, 2, 3];
    let owned: Vec<i32> = v.iter().copied().collect();
    let idx: i32 = 1;
    println!("{owned:?} {}", owned[idx as usize]);
}

Output:

Item { name: "sword", price: 12.5 } equal: true
1 | 2 | 3
a | b
[19.0, 21.5, 23.25]
cheapest: potion
[1, 2, 3] 2

Practice it