Hashing a struct that is all ref


#1
  1. I have the following:
pub struct Object<'a> {
  FooWrapper(&'a Foo),
  BarWrapper(&'a Bar),
  CatWrapper(&'a Cat)
}
  1. If I try to #[derive(Hash)], it wants me to implement Hash on Foo/Bar/Cat.

  2. However, if & are just pointers, I want to be able to hash just based on pointer address. Is there a way ot make this happen?


Is this custom Eq/Hash impl "correct"?
#2

this is not possible due to the blanket impl

impl<T> Hash for &T 
where : Hash + ?Sized
{
    ...
}

and changing this would lead to unexpected behavior.

At best you would have to wait until specialization comes to do this.


btw, did you mean enum instead of struct?


#3

If it were made how you mentioned it, it would probably be fine, as though it would probably use a pointer in that case, and hash that because there’s no guarantee that T implements Hash, but unfortunately it’s implemented as such:

impl<T: ?Sized + Hash> Hash for &T {
    fn hash<H: Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

And so, it’s impossible to implement Hash on &T again with another bound

Edit: it’s shown here that what @zeroexcuses wants is possible, it just requires an explicit cast, therefore disallowing it from being blanket-implemented for references so as to treat them as pointers… Which brings up an idea, could perhaps a Deref<T> solution work?


#4
  1. Yes, I meant enum, not struct.

  2. I also mispphrased my question – I wanted to ask : how can I write a customer hasher (not modify the behaviour of deerive(Hash)

and it turns out the solution to this is:

impl<'a> Hash for .... {
  fn hash<H: Hasher>(&self, state: &mut H) {
   ...
  state.write( .... as *const char); // grab ptr vaue of ref
}

#5

Yeah, that solution would work but would have to be implemented manually for foo cat and bar, which is what was presumed from your original question…