Description
This test currently fails:
use bytes::Bytes;
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
};
fn hash<T: Hash>(v: &T) -> u64 {
let mut sh = DefaultHasher::new();
v.hash(&mut sh);
sh.finish()
}
#[test]
fn hash_fail() {
let s = "test string";
let b = Bytes::from(s);
assert_eq!(b, s);
assert!(
hash(&b) == hash(&s),
"Hashes differ even though values compare as equal",
);
}
For things to be proper, this test should not even compile due to lack of an equality impl.
The PartialEq
implementations that make the equality operators work between a Bytes
value and a string, while convenient, allow two logically equal values to have different hashes. This violates the contract of Hash
and therefore is a no-no. The standard library avoids pairing strings and byte slices in equality and comparison operators, and even burns extra CPU to make a string's Hash
output pointedly different from that of an equivalent byte slice.
This issue does not affect HashTable
because there is no Borrow
impl to cross between the key types. But the inconsistency is lurking and can bite even in generic code using Hash
by the book.