diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index 5c369ebb5b45d..8225ad6a2d635 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -159,11 +159,16 @@ impl FromStableHash for Fingerprint { #[inline] fn from(hash: Self::Hash) -> Self { - let bytes = hash.as_bytes(); - Fingerprint( - u64::from_ne_bytes(bytes[0..8].try_into().unwrap()), - u64::from_ne_bytes(bytes[8..16].try_into().unwrap()), - ) + let bytes: &[u8; 32] = hash.as_bytes(); + + let p0 = u64::from_le_bytes(bytes[0..8].try_into().unwrap()); + let p1 = u64::from_le_bytes(bytes[8..16].try_into().unwrap()); + let p2 = u64::from_le_bytes(bytes[16..24].try_into().unwrap()); + let p3 = u64::from_le_bytes(bytes[24..32].try_into().unwrap()); + + // See https://stackoverflow.com/a/27952689 on why this function is + // implemented this way. + Fingerprint(p0.wrapping_mul(3).wrapping_add(p1), p2.wrapping_mul(3).wrapping_add(p3)) } } diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs index 935fc6b417a33..1733e64cf4cd5 100644 --- a/compiler/rustc_data_structures/src/hashes.rs +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -62,7 +62,19 @@ impl FromStableHash for Hash64 { #[inline] fn from(hash: Self::Hash) -> Self { let bytes = hash.as_bytes(); - Self { inner: u64::from_ne_bytes(bytes[0..8].try_into().unwrap()) } + + let p0 = u64::from_le_bytes(bytes[0..8].try_into().unwrap()); + let p1 = u64::from_le_bytes(bytes[8..16].try_into().unwrap()); + let p2 = u64::from_le_bytes(bytes[16..24].try_into().unwrap()); + let p3 = u64::from_le_bytes(bytes[24..32].try_into().unwrap()); + + // See https://stackoverflow.com/a/27952689 on why this function is + // implemented this way. + let m0 = p0.wrapping_mul(3).wrapping_add(p1); + let m1 = p2.wrapping_mul(3).wrapping_add(p3); + let h = m0.wrapping_mul(3).wrapping_add(m1); + + Self { inner: h } } } @@ -130,7 +142,18 @@ impl FromStableHash for Hash128 { #[inline] fn from(hash: Self::Hash) -> Self { let bytes = hash.as_bytes(); - Self { inner: u128::from_ne_bytes(bytes[0..16].try_into().unwrap()) } + + let p0 = u64::from_le_bytes(bytes[0..8].try_into().unwrap()); + let p1 = u64::from_le_bytes(bytes[8..16].try_into().unwrap()); + let p2 = u64::from_le_bytes(bytes[16..24].try_into().unwrap()); + let p3 = u64::from_le_bytes(bytes[24..32].try_into().unwrap()); + + // See https://stackoverflow.com/a/27952689 on why this function is + // implemented this way. + let upper = p0.wrapping_mul(3).wrapping_add(p1); + let lower = p2.wrapping_mul(3).wrapping_add(p3); + + Self { inner: u128::from(lower) | (u128::from(upper) << 64) } } }