Rust で HashSet の要素や HashMap のキーに使う型は Eq と Hash トレイトを実装している必要がある
HashSet in std::collections - Rust
HashMap in std::collections - Rust
自前の構造体を HashSet の要素にしたり、HashMap のキーに使用するとコンパイルエラーになる。
use std::collections::HashSet; fn main() { { struct MyFoo { x: i32, } let mut hs: HashSet<MyFoo> = HashSet::new(); hs.insert(MyFoo { x: 123 }); hs.insert(MyFoo { x: 234 }); for e in hs.iter() { println!("{}", e.x); } } }
error[E0599]: the method `insert` exists for struct `HashSet<MyFoo>`, but its trait bounds were not satisfied --> examples\hm_error.rs:8:12 | 4 | struct MyFoo { | ------------ | | | doesn't satisfy `MyFoo: Eq` | doesn't satisfy `MyFoo: Hash` ... 8 | hs.insert(MyFoo { x: 123 }); | ^^^^^^ method cannot be called on `HashSet<MyFoo>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `MyFoo: Eq` `MyFoo: Hash` help: consider annotating `MyFoo` with `#[derive(Eq, Hash)]` | 4 | #[derive(Eq, Hash)] | error[E0599]: the method `insert` exists for struct `HashSet<MyFoo>`, but its trait bounds were not satisfied --> examples\hm_error.rs:9:12 | 4 | struct MyFoo { | ------------ | | | doesn't satisfy `MyFoo: Eq` | doesn't satisfy `MyFoo: Hash` ... 9 | hs.insert(MyFoo { x: 234 }); | ^^^^^^ method cannot be called on `HashSet<MyFoo>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `MyFoo: Eq` `MyFoo: Hash` help: consider annotating `MyFoo` with `#[derive(Eq, Hash)]` | 4 | #[derive(Eq, Hash)] | For more information about this error, try `rustc --explain E0599`.
derive で Hash と Eq をつければ良いようだ。しかしその2つだとインスタンス同士の比較ができなくて、PartialEq もつけるといいよ!、とメッセージが出るので、そのようにするとうまくいった。
#[derive(Hash, Eq, PartialEq)] struct MyFoo { x: i32, }
同様に、HashMap のキーのときも同じ対応でいけた。
#[derive(Hash, Eq, PartialEq)] struct MyFoo { x: i32, } let mut hm: HashMap<MyFoo, &str> = HashMap::new(); hm.insert(MyFoo { x: 123 }, "123"); hm.insert(MyFoo { x: 234 }, "234"); for (k, v) in hm.iter() { println!("{}, {}", k.x, v); }