diff options
| author | bors <bors@rust-lang.org> | 2022-04-09 02:31:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-04-09 02:31:24 +0000 |
| commit | e980c6295582792e4a7c2d67e33cece60c170115 (patch) | |
| tree | 0e52df53a2dba63646376b4f633f595652d05bd4 /compiler/rustc_data_structures/src | |
| parent | 340f6491bed3525acfabbdbd1545b6aee2fca62b (diff) | |
| parent | 25d6f8e0f647f865775158f35408724278145c50 (diff) | |
| download | rust-e980c6295582792e4a7c2d67e33cece60c170115.tar.gz rust-e980c6295582792e4a7c2d67e33cece60c170115.zip | |
Auto merge of #95524 - oli-obk:cached_stable_hash_cleanups, r=nnethercote
Cached stable hash cleanups r? `@nnethercote` Add a sanity assertion in debug mode to check that the cached hashes are actually the ones we get if we compute the hash each time. Add a new data structure that bundles all the hash-caching work to make it easier to re-use it for different interned data structures
Diffstat (limited to 'compiler/rustc_data_structures/src')
| -rw-r--r-- | compiler/rustc_data_structures/src/intern.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 7a320b10b60..009b5d5340a 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,87 @@ 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)); +} + +/// A helper type that you can wrap round your own type in order to automatically +/// cache the stable hash on creation and not recompute it whenever the stable hash +/// of the type is computed. +/// This is only done in incremental mode. You can also opt out of caching by using +/// StableHash::ZERO for the hash, in which case the hash gets computed each time. +/// This is useful if you have values that you intern but never (can?) use for stable +/// hashing. +#[derive(Copy, Clone)] +pub struct WithStableHash<T> { + pub internee: T, + pub stable_hash: Fingerprint, +} + +impl<T: PartialEq> PartialEq for WithStableHash<T> { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.internee.eq(&other.internee) + } +} + +impl<T: Eq> Eq for WithStableHash<T> {} + +impl<T: Ord> PartialOrd for WithStableHash<T> { + fn partial_cmp(&self, other: &WithStableHash<T>) -> Option<Ordering> { + Some(self.internee.cmp(&other.internee)) + } +} + +impl<T: Ord> Ord for WithStableHash<T> { + fn cmp(&self, other: &WithStableHash<T>) -> Ordering { + self.internee.cmp(&other.internee) + } +} + +impl<T> Deref for WithStableHash<T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.internee + } +} + +impl<T: Hash> Hash for WithStableHash<T> { + #[inline] + fn hash<H: Hasher>(&self, s: &mut H) { + self.internee.hash(s) + } +} + +impl<T: HashStable<CTX>, CTX: InternedHashingContext> HashStable<CTX> for WithStableHash<T> { + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { + // 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() + }; + if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO { + assert_eq!( + stable_hash, self.stable_hash, + "cached stable hash does not match freshly computed stable hash" + ); + } + stable_hash.hash_stable(hcx, hasher); + } else { + self.stable_hash.hash_stable(hcx, hasher); + } + } +} + #[cfg(test)] mod tests; |
