-
Notifications
You must be signed in to change notification settings - Fork 2
Description
The behavior that needs to be guaranteed for equivalent instances is described in the document of std::hash::Hasher
This trait provides no guarantees about how the various
write_*methods are
defined and implementations of [Hash] should not assume that they work one
way or another. You cannot assume, for example, that a [write_u32] call is
equivalent to four calls of [write_u8]. Nor can you assume that adjacent
writecalls are merged, so it's possible, for example, that# fn foo(hasher: &mut impl std::hash::Hasher) { hasher.write(&[1, 2]); hasher.write(&[3, 4, 5, 6]); # }and
# fn foo(hasher: &mut impl std::hash::Hasher) { hasher.write(&[1, 2, 3, 4]); hasher.write(&[5, 6]); # }end up producing different hashes.
Thus to produce the same hash value, [
Hash] implementations must ensure
for equivalent items that exactly the same sequence of calls is made -- the
same methods with the same parameters in the same order.
Although CachedHash implements Borrow<T>, its hash behavior attempts to equate write_u64 with unknown write calls
This does not match the description in Borrow document
In particular
Eq,OrdandHashmust be equivalent for
borrowed and owned values:x.borrow() == y.borrow()should give the
same result asx == y.
Lines 169 to 182 in 28fafd6
| impl<T: Eq + Hash, BH: BuildHasher> Hash for CachedHash<T, BH> { | |
| fn hash<H2: Hasher>(&self, state: &mut H2) { | |
| if let Some(hash) = self.hash.get_raw() { | |
| state.write_u64(hash); | |
| } else { | |
| let mut hasher = self.build_hasher.build_hasher(); | |
| self.value.hash(&mut hasher); | |
| // AtomicOptionNonZeroU64 can only store non-zero values so we create a small collision by bumping up hash 0 to 1. | |
| let hash = NonZeroU64::new(hasher.finish()).unwrap_or(NonZeroU64::new(1).unwrap()); | |
| self.hash.set(Some(hash)); | |
| state.write_u64(hash.into()); | |
| } | |
| } | |
| } |
Lines 202 to 206 in 28fafd6
| impl<T: Eq + Hash, BH: BuildHasher> Borrow<T> for CachedHash<T, BH> { | |
| fn borrow(&self) -> &T { | |
| Self::get(self) | |
| } | |
| } |