error[E0277]: the trait bound `Type: Trait` is not satisfied

期待されるトレイト境界に型が適合しなかった。

パターン

パターン A

基本形

単純にトレイト境界を満たさないパターン。

サンプル

以下では、関数 func の引数 argMyTrait 境界に適合しなければならない。
しかし、実引数として指定された値 falsebool 型でそれに適合していない。


fn main() {
    func(false);
}

fn func<T: MyTrait>(arg: T) {
    println!("arg: {}", arg.text());
}

trait MyTrait {
    fn text(&self) -> &str;
}

error[E0277]: the trait bound `bool: MyTrait` is not satisfied
 --> src\main.rs:2:10
  |
2 |     func(false);
  |     ---- ^^^^^ the trait `MyTrait` is not implemented for `bool`
  |     |
  |     required by a bound introduced by this call
  |
help: this trait has no implementations, consider adding one
 --> src\main.rs:9:1
  |
9 | trait MyTrait {
  | ^^^^^^^^^^^^^
note: required by a bound in `func`
 --> src\main.rs:5:12
  |
5 | fn func<T: MyTrait>(arg: T) {
  |            ^^^^^^^ required by this bound in `func`

解決策

トレイト境界を満たすよう型にトレイト実装を追加する。


fn main() {
    func(false);
}

fn func<T: MyTrait>(arg: T) {
    println!("arg: {}", arg.text());
}

trait MyTrait {
    fn text(&self) -> &str;
}

impl MyTrait for bool {
    fn text(&self) -> &str {
        if *self { "T" } else { "F" }
    }
}

パターン B

derive 属性

問題のトレイト境界が derive 属性によるパターン。

derive 属性 - 型パラメタの影響』で紹介する通り、derive 属性は型パラメタについての境界を導入する場合が多い。この境界に違反するとエラーになる。なお、下記のサンプルではエラーメッセージがその境界 T: Default について指摘しているが、ソース中に該当箇所が存在しない。そのため、混乱しやすい。

サンプル

以下では、MyVec<T>Deault の実装は derive 属性に由来するため、T: Default の境界を持つ。しかし、MyVec::default() の呼出箇所の TClone しか実装していない。


fn main() {
    let values = values(1, 3);
    assert_eq!(values.0, vec![1, 1, 1]);
}

fn values<T: Clone>(value: T, len: usize) -> MyVec<T> {
    let mut ret = MyVec::default();
    for _ in 0..len {
        ret.0.push(value.clone());
    }

    ret
}

#[derive(Default, Clone, PartialEq)]
struct MyVec<T>(Vec<T>);

error[E0277]: the trait bound `T: Default` is not satisfied
  --> src\main.rs:7:19
   |
 7 |     let mut ret = MyVec::default();
   |                   ^^^^^ the trait `Default` is not implemented for `T`
   |
note: required for `MyVec<T>` to implement `Default`
  --> src\main.rs:15:10
   |
15 | #[derive(Default, Clone, PartialEq)]
   |          ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
help: consider further restricting type parameter `T` with trait `Default`
   |
 6 | fn values<T: Clone + std::default::Default>(value: T, len: usize) -> MyVec<T> {
   |                    +++++++++++++++++++++++

解決策

derive 属性による境界が問題の場合、それを除去したコードを手動で記述する。


fn main() {
    let values = values(1, 3);
    assert_eq!(values.0, vec![1, 1, 1]);
}

fn values<T: Clone>(value: T, len: usize) -> MyVec<T> {
    let mut ret = MyVec::default();
    for _ in 0..len {
        ret.0.push(value.clone());
    }

    ret
}

#[derive(Clone, PartialEq)]
struct MyVec<T>(Vec<T>);

impl<T> Default for MyVec<T> {
    fn default() -> Self {
        Self(Default::default())
    }
}