about summary refs log tree commit diff
path: root/compiler/rustc_hashes/src/lib.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-02-17 11:18:33 +0000
committerbors <bors@rust-lang.org>2025-02-17 11:18:33 +0000
commit2162e9d4b18525e4eb542fed9985921276512d7c (patch)
treee8df98cb0ac63ee1d77d4ef971502ae0f89e654b /compiler/rustc_hashes/src/lib.rs
parent273465e1f2932a30a5b56ac95859cdc86f3f33fa (diff)
parent183fc30867571cc585020999b42b0f5244dfda4a (diff)
downloadrust-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.rs131
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)
+    }
+}