about summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-03-01 14:51:08 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-03-31 14:54:04 +0000
commit00c24dd8cec6c57ccbfb376c4a2f47b5f6e39401 (patch)
tree0050c3bd37f4b882b725d968163f689631e4197b /compiler/rustc_data_structures/src
parentdf20355fa9fa5e9fb89be4e4bfee8a643bb7a23e (diff)
downloadrust-00c24dd8cec6c57ccbfb376c4a2f47b5f6e39401.tar.gz
rust-00c24dd8cec6c57ccbfb376c4a2f47b5f6e39401.zip
Move stable hash from TyS into a datastructure that can be shared with other interned types.
Diffstat (limited to 'compiler/rustc_data_structures/src')
-rw-r--r--compiler/rustc_data_structures/src/intern.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index 7a320b10b60..1b187cd306e 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -4,6 +4,8 @@ use std::hash::{Hash, Hasher};
 use std::ops::Deref;
 use std::ptr;
 
+use crate::fingerprint::Fingerprint;
+
 mod private {
     #[derive(Clone, Copy, Debug)]
     pub struct PrivateZst;
@@ -108,5 +110,76 @@ where
     }
 }
 
+/// A helper trait so that `Interned` things can cache stable hashes reproducibly.
+pub trait InternedHashingContext {
+    fn with_def_path_and_no_spans(&mut self, f: impl FnOnce(&mut Self));
+}
+
+#[derive(Copy, Clone)]
+pub struct InTy<T> {
+    pub internee: T,
+    pub stable_hash: Fingerprint,
+}
+
+impl<T: PartialEq> PartialEq for InTy<T> {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.internee.eq(&other.internee)
+    }
+}
+
+impl<T: Eq> Eq for InTy<T> {}
+
+impl<T: Ord> PartialOrd for InTy<T> {
+    fn partial_cmp(&self, other: &InTy<T>) -> Option<Ordering> {
+        Some(self.internee.cmp(&other.internee))
+    }
+}
+
+impl<T: Ord> Ord for InTy<T> {
+    fn cmp(&self, other: &InTy<T>) -> Ordering {
+        self.internee.cmp(&other.internee)
+    }
+}
+
+impl<T> Deref for InTy<T> {
+    type Target = T;
+
+    #[inline]
+    fn deref(&self) -> &T {
+        &self.internee
+    }
+}
+
+impl<T: Hash> Hash for InTy<T> {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        self.internee.hash(s)
+    }
+}
+
+impl<T: HashStable<CTX>, CTX: InternedHashingContext> HashStable<CTX> for InTy<T> {
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        let stable_hash = self.stable_hash;
+
+        if stable_hash == Fingerprint::ZERO {
+            // No cached hash available. This can only mean that incremental is disabled.
+            // We don't cache stable hashes in non-incremental mode, because they are used
+            // so rarely that the performance actually suffers.
+
+            // We need to build the hash as if we cached it and then hash that hash, as
+            // otherwise the hashes will differ between cached and non-cached mode.
+            let stable_hash: Fingerprint = {
+                let mut hasher = StableHasher::new();
+                hcx.with_def_path_and_no_spans(|hcx| self.internee.hash_stable(hcx, &mut hasher));
+                hasher.finish()
+            };
+            stable_hash.hash_stable(hcx, hasher);
+        } else {
+            stable_hash.hash_stable(hcx, hasher);
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests;