Misleading error message? #[derive(Eq, Hash, PartialEq)]

Hi all.

I'm doing something wrong here:

use std::collections::HashSet;

struct Thing<T, P> {
    set: HashSet<Abc<T, P>>
}

impl<T, P> Thing<T, P> {

    fn new() -> Self {
        Self { set: HashSet::new() }
    }

    fn add(&mut self, a: T, b: P, c: T, d: P) {

        self.set.insert(Abc(a, b, c, d));

    }

}

#[derive(Eq, Hash, PartialEq)]
struct Abc<T, P>(T, P, T, P);


fn main() {

    let mut h = HashSet::<Abc<i32, String>>::new();
    h.insert(Abc(10, "A".into(), 20, "B".into()));

}

but I don't get why the error message suggests me to add #[derive(Eq, Hash, PartialEq)] even if it is already there:

error[E0599]: the method `insert` exists for struct `HashSet<Abc<T, P>>`, but its trait bounds were not satisfied
  --> src/main.rs:16:18
   |
16 |         self.set.insert(Abc(a, b, c, d));
   |                  ^^^^^^
...
24 | struct Abc<T, P>(T, P, T, P);
   | ----------------
   | |
   | doesn't satisfy `Abc<T, P>: Eq`
   | doesn't satisfy `Abc<T, P>: Hash`
   |
   = note: the following trait bounds were not satisfied:
           `Abc<T, P>: Eq`
           `Abc<T, P>: Hash`
help: consider annotating `Abc<T, P>` with `#[derive(Eq, Hash, PartialEq)]`
   |
24 | #[derive(Eq, Hash, PartialEq)]
   |

Why this error message? And why #[derive(Eq, Hash, PartialEq)] isn't enough?

Thanks!

you should write where bound in impl like this

impl<T, P> Thing<T, P>
where
    T: Eq + Hash,
    P: Eq + Hash,
{
    fn new() -> Self {
        Self {
            set: HashSet::new(),
        }
    }

    fn add(&mut self, a: T, b: P, c: T, d: P) {
        self.set.insert(Abc(a, b, c, d));
    }
}

the #[derive(Eq)] expand to some code like this:

impl<T, P> Eq for Abc<T, P>
where
    T: Eq + Hash,
    P: Eq + Hash,
{
   ...
}

that is, only T and P both Eq and Hash, the Abc<T, P> can be Hash and Eq. so in your add method, you must tell the compiler that the T and P in Thing also impl Eq and Hash

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.