diff options
| author | bors <bors@rust-lang.org> | 2025-02-17 11:18:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-02-17 11:18:33 +0000 |
| commit | 2162e9d4b18525e4eb542fed9985921276512d7c (patch) | |
| tree | e8df98cb0ac63ee1d77d4ef971502ae0f89e654b /compiler/rustc_hashes/src/lib.rs | |
| parent | 273465e1f2932a30a5b56ac95859cdc86f3f33fa (diff) | |
| parent | 183fc30867571cc585020999b42b0f5244dfda4a (diff) | |
| download | rust-2162e9d4b18525e4eb542fed9985921276512d7c.tar.gz rust-2162e9d4b18525e4eb542fed9985921276512d7c.zip | |
Auto merge of #137164 - matthiaskrgr:rollup-dj5826k, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #137095 (Replace some u64 hashes with Hash64) - #137100 (HIR analysis: Remove unnecessary abstraction over list of clauses) - #137105 (Restrict DerefPure for Cow<T> impl to T = impl Clone, [impl Clone], str.) - #137120 (Enable `relative-path-include-bytes-132203` rustdoc-ui test on Windows) - #137125 (Re-add missing empty lines in the releases notes) - #137145 (use add-core-stubs / minicore for a few more tests) - #137149 (Remove SSE ABI from i586-pc-windows-msvc) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_hashes/src/lib.rs')
| -rw-r--r-- | compiler/rustc_hashes/src/lib.rs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/compiler/rustc_hashes/src/lib.rs b/compiler/rustc_hashes/src/lib.rs new file mode 100644 index 00000000000..3755caaaa29 --- /dev/null +++ b/compiler/rustc_hashes/src/lib.rs @@ -0,0 +1,131 @@ +//! rustc encodes a lot of hashes. If hashes are stored as `u64` or `u128`, a `derive(Encodable)` +//! will apply varint encoding to the hashes, which is less efficient than directly encoding the 8 +//! or 16 bytes of the hash. And if that hash depends on the `StableCrateHash` (which most in rustc +//! do), the varint encoding will make the number of bytes encoded fluctuate between compiler +//! versions. +//! +//! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`. +//! `Hash64` and `Hash128` expose some utility functions to encourage users to not extract the inner +//! hash value as an integer type and accidentally apply varint encoding to it. +//! +//! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct +//! and decompose these types into constituent pieces. The point of these types is only to +//! connect the fact that they can only be produced by a `StableHasher` to their +//! `Encode`/`Decode` impls. + +use std::fmt; +use std::ops::BitXorAssign; + +use rustc_stable_hash::{FromStableHash, SipHasher128Hash as StableHasherHash}; + +/// A `u64` but encoded with a fixed size; for hashes this encoding is more compact than `u64`. +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +pub struct Hash64 { + inner: u64, +} + +impl Hash64 { + pub const ZERO: Hash64 = Hash64 { inner: 0 }; + + #[inline] + pub fn new(n: u64) -> Self { + Self { inner: n } + } + + #[inline] + pub fn as_u64(self) -> u64 { + self.inner + } + + #[inline] + pub fn wrapping_add(self, other: Self) -> Self { + Self { inner: self.inner.wrapping_add(other.inner) } + } +} + +impl BitXorAssign<u64> for Hash64 { + #[inline] + fn bitxor_assign(&mut self, rhs: u64) { + self.inner ^= rhs; + } +} + +impl FromStableHash for Hash64 { + type Hash = StableHasherHash; + + #[inline] + fn from(StableHasherHash([_0, __1]): Self::Hash) -> Self { + Self { inner: _0 } + } +} + +impl fmt::Debug for Hash64 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl fmt::LowerHex for Hash64 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.inner, f) + } +} + +/// A `u128` but encoded with a fixed size; for hashes this encoding is more compact than `u128`. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] +pub struct Hash128 { + inner: u128, +} + +// We expect Hash128 to be well mixed. So there's no point in hashing both parts. +// +// This also allows using Hash128-containing types in UnHash-based hashmaps, which would otherwise +// debug_assert! that we're hashing more than a single u64. +impl std::hash::Hash for Hash128 { + fn hash<H: std::hash::Hasher>(&self, h: &mut H) { + h.write_u64(self.truncate().as_u64()); + } +} + +impl Hash128 { + #[inline] + pub fn new(n: u128) -> Self { + Self { inner: n } + } + + #[inline] + pub fn truncate(self) -> Hash64 { + Hash64 { inner: self.inner as u64 } + } + + #[inline] + pub fn wrapping_add(self, other: Self) -> Self { + Self { inner: self.inner.wrapping_add(other.inner) } + } + + #[inline] + pub fn as_u128(self) -> u128 { + self.inner + } +} + +impl FromStableHash for Hash128 { + type Hash = StableHasherHash; + + #[inline] + fn from(StableHasherHash([_0, _1]): Self::Hash) -> Self { + Self { inner: u128::from(_0) | (u128::from(_1) << 64) } + } +} + +impl fmt::Debug for Hash128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl fmt::LowerHex for Hash128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.inner, f) + } +} |
