1
Fork 0

Improve `Allocation::hash

Exhaustively destructure and ignore `()`
This commit is contained in:
Nilstrieb 2023-04-09 22:38:48 +02:00
parent 5a90de8f5e
commit 6fceb0f645

View file

@ -109,26 +109,34 @@ const MAX_HASHED_BUFFER_LEN: usize = 2 * MAX_BYTES_TO_HASH;
// large. // large.
impl hash::Hash for Allocation { impl hash::Hash for Allocation {
fn hash<H: hash::Hasher>(&self, state: &mut H) { fn hash<H: hash::Hasher>(&self, state: &mut H) {
let Self {
bytes,
provenance,
init_mask,
align,
mutability,
extra: _, // don't bother hashing ()
} = self;
// Partially hash the `bytes` buffer when it is large. To limit collisions with common // Partially hash the `bytes` buffer when it is large. To limit collisions with common
// prefixes and suffixes, we hash the length and some slices of the buffer. // prefixes and suffixes, we hash the length and some slices of the buffer.
let byte_count = self.bytes.len(); let byte_count = bytes.len();
if byte_count > MAX_HASHED_BUFFER_LEN { if byte_count > MAX_HASHED_BUFFER_LEN {
// Hash the buffer's length. // Hash the buffer's length.
byte_count.hash(state); byte_count.hash(state);
// And its head and tail. // And its head and tail.
self.bytes[..MAX_BYTES_TO_HASH].hash(state); bytes[..MAX_BYTES_TO_HASH].hash(state);
self.bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state); bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state);
} else { } else {
self.bytes.hash(state); bytes.hash(state);
} }
// Hash the other fields as usual. // Hash the other fields as usual.
self.provenance.hash(state); provenance.hash(state);
self.init_mask.hash(state); init_mask.hash(state);
self.align.hash(state); align.hash(state);
self.mutability.hash(state); mutability.hash(state);
self.extra.hash(state);
} }
} }