HashMap with array as key? (Hash not implemented)

I am trying to use a HashMap using an array as the keys; however, I am getting an error and I am not sure how to resolve it. User does not generate an error and the [u8;64] is a primitive, so I would not expect it to be a source of the error (though it may?) and I am not sure how to implement Hash on a HashMap. All of the examples I see are on things like structs.

I did try creating a struct Id with a field id: [u8;64] and using the serde_big_array crate to derive serialize,deserialize and hash on it. Which did not error, but when I tried to use the Id as a key, I got the same error.

Also, serde_big_array did not work to directly resolve the issue below either. And, changing the array to a slice (&[u8]) also did not solve the issue.

The error:

the trait `std::hash::Hash` is not implemented for `HashMap<[u8; 64], User>`

The code resulting in the error:

#[derive(Default,Debug,Serialize,Deserialize,PartialEq, PartialOrd,Hash,Eq)]
struct User {
    name: Option<String>,
    groups: BTreeSet<UserGroup>
}
#[derive(Serialize,Deserialize,Hash,Debug)]
pub struct Mapped{
    users: HashMap<[u8;64], User>
}

The problem is not that [u8;64] does not implement Hash (it does). The problem is that you are trying to derive Hash on Mapped. HashMap does not implement Hash, so you can't derive Hash on a struct that contains it as a field. BTreeMap does implement Hash, try using it instead of HashMap.

1 Like

The problem is not the array. HashMap never implements Hash for any type, the reason being that its ordering is pseudo-random (so not reliable), and hashing is generic, but hashers aren't commutative in general.

5 Likes

You have the same post before: Hash not implemented, why can't it be derived?

3 Likes

Oh, yeah. @Jcarp please do not post duplicates.

Didn't realize it was a duplicate. Feel free to remove it.

Duplicates aren’t problematic per say, we are not a Q and A platform that (possibly unhelpfully) closes all duplicate questions or anything like that; but of course it’s good practice to try to search for existing questions at least a little bit to see if it’s an problem with an easy to find existing solution; and even more so then, it makes sense to try to remember one’s own questions.

On the other hand, I suppose this just maybe just means you didn’t really understand what the underlying problem actually was, the last time you asked, and maybe just ended up with a “I’ll use BTreeSet if that works in this case” approach. Also, people’s memory differs; one can simply forget something 2 weeks later… Let’s hope, the re-iteration brings you one step closer to an understanding! :slight_smile:


For better understanding of the code here, some relevant thing to know are

  • how derive, roughly, operates; in particular that it operates (for most traits) by requiring the same trait to be implemented for the type of the fields as well
  • how to look up trait implementations in the standard library; for the types at hand, e.g. looking at the Hash trait’s docs, you’ll find BTreeSet somewhere in the long list of implementors (use the search functionality of your web browser to find types more quickly in such a long listing), namely here, whereas e.g. HashMap is no-where to be found. The same kind of information can also be seen on each type’s page, e.g. here are all the traits that BTreeMap implements, including Hash (for this page, there is also a good overview in the sidebar on the left).

And general knowledge of what a trait is in the first place is of course useful, so check the chapter in the book in case you haven’t read it already.


In case you were aware that the code is some modification of the code in the other question but just weren’t sure if the problem you’ve come across was similar or entirely different, note for future reference, that it can also be a good approach to just say “I’ve asked question(s) about versions of this example code before [here](www.link.address)”, just to make it easier for anyone answering to possibly build on previous answers, or avoid repeating explanations others have already given. This would typically be enough to avoid anyone from raising objections for “duplicates”. The same applies e.g. also for cross-posts (occasionally people post here and on stack overflow) which are generally mostly accepted as long as you make sure to link between the two posts, because the main concern is to avoid unnecessary duplicate efforts on the answerers’ side.

3 Likes

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.