Let a portion of DefPathHash uniquely identify the DefPath's crate.

This allows to directly map from a DefPathHash to the crate it
originates from, without constructing side tables to do that mapping.

It also allows to reliably and cheaply check for DefPathHash collisions.
This commit is contained in:
Michael Woerister 2021-01-27 14:28:07 +01:00 committed by Michael Woerister
parent a3ed564c13
commit 22d489be76
12 changed files with 181 additions and 27 deletions

View file

@ -7,11 +7,17 @@ use std::hash::{Hash, Hasher};
use std::mem::{self, MaybeUninit};
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
#[repr(C)]
pub struct Fingerprint(u64, u64);
impl Fingerprint {
pub const ZERO: Fingerprint = Fingerprint(0, 0);
#[inline]
pub fn new(_0: u64, _1: u64) -> Fingerprint {
Fingerprint(_0, _1)
}
#[inline]
pub fn from_smaller_hash(hash: u64) -> Fingerprint {
Fingerprint(hash, hash)
@ -19,7 +25,12 @@ impl Fingerprint {
#[inline]
pub fn to_smaller_hash(&self) -> u64 {
self.0
// Even though both halves of the fingerprint are expected to be good
// quality hash values, let's still combine the two values because the
// Fingerprints in DefPathHash have the StableCrateId portion which is
// the same for all DefPathHashes from the same crate. Combining the
// two halfs makes sure we get a good quality hash in such cases too.
self.0.wrapping_mul(3).wrapping_add(self.1)
}
#[inline]
@ -93,7 +104,7 @@ impl FingerprintHasher for crate::unhash::Unhasher {
#[inline]
fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
// `Unhasher` only wants a single `u64`
self.write_u64(fingerprint.0);
self.write_u64(fingerprint.0.wrapping_add(fingerprint.1));
}
}