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
write calls 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, Ord and Hash must be equivalent for
borrowed and owned values: x.borrow() == y.borrow() should give the
same result as x == y.
|
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()); |
|
} |
|
} |
|
} |
|
impl<T: Eq + Hash, BH: BuildHasher> Borrow<T> for CachedHash<T, BH> { |
|
fn borrow(&self) -> &T { |
|
Self::get(self) |
|
} |
|
} |
The behavior that needs to be guaranteed for equivalent instances is described in the document of
std::hash::HasherAlthough CachedHash implements
Borrow<T>, its hash behavior attempts to equatewrite_u64with unknown write callsThis does not match the description in
Borrowdocumentcachedhash/src/cachedhash.rs
Lines 169 to 182 in 28fafd6
cachedhash/src/cachedhash.rs
Lines 202 to 206 in 28fafd6