diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-03-01 14:51:08 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-03-31 14:54:04 +0000 |
| commit | 00c24dd8cec6c57ccbfb376c4a2f47b5f6e39401 (patch) | |
| tree | 0050c3bd37f4b882b725d968163f689631e4197b /compiler/rustc_data_structures/src | |
| parent | df20355fa9fa5e9fb89be4e4bfee8a643bb7a23e (diff) | |
| download | rust-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.rs | 73 |
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; |
