summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/impls_ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty/impls_ty.rs')
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs135
1 files changed, 135 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
new file mode 100644
index 000000000..cd00b26b8
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -0,0 +1,135 @@
+//! This module contains `HashStable` implementations for various data types
+//! from `rustc_middle::ty` in no particular order.
+
+use crate::middle::region;
+use crate::mir;
+use crate::ty;
+use crate::ty::fast_reject::SimplifiedType;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::HashingControls;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_query_system::ich::StableHashingContext;
+use std::cell::RefCell;
+
+impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
+where
+ T: HashStable<StableHashingContext<'a>>,
+{
+ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+ thread_local! {
+ static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
+ RefCell::new(Default::default());
+ }
+
+ let hash = CACHE.with(|cache| {
+ let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls());
+ if let Some(&hash) = cache.borrow().get(&key) {
+ return hash;
+ }
+
+ let mut hasher = StableHasher::new();
+ (&self[..]).hash_stable(hcx, &mut hasher);
+
+ let hash: Fingerprint = hasher.finish();
+ cache.borrow_mut().insert(key, hash);
+ hash
+ });
+
+ hash.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
+where
+ T: HashStable<StableHashingContext<'a>>,
+{
+ type KeyType = Fingerprint;
+
+ #[inline]
+ fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
+ let mut hasher = StableHasher::new();
+ let mut hcx: StableHashingContext<'a> = hcx.clone();
+ self.hash_stable(&mut hcx, &mut hasher);
+ hasher.finish()
+ }
+}
+
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType {
+ type KeyType = Fingerprint;
+
+ #[inline]
+ fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
+ let mut hasher = StableHasher::new();
+ let mut hcx: StableHashingContext<'a> = hcx.clone();
+ self.hash_stable(&mut hcx, &mut hasher);
+ hasher.finish()
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
+ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+ self.unpack().hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
+ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+ match self {
+ // WARNING: We dedup cache the `HashStable` results for `List`
+ // while ignoring types and freely transmute
+ // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
+ // See `fn intern_type_list` for more details.
+ //
+ // We therefore hash types without adding a hash for their discriminant.
+ //
+ // In order to make it very unlikely for the sequence of bytes being hashed for
+ // a `GenericArgKind::Type` to be the same as the sequence of bytes being
+ // hashed for one of the other variants, we hash some very high number instead
+ // of their actual discriminant since `TyKind` should never start with anything
+ // that high.
+ ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
+ ty::subst::GenericArgKind::Const(ct) => {
+ 0xF3u8.hash_stable(hcx, hasher);
+ ct.hash_stable(hcx, hasher);
+ }
+ ty::subst::GenericArgKind::Lifetime(lt) => {
+ 0xF5u8.hash_stable(hcx, hasher);
+ lt.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
+
+// AllocIds get resolved to whatever they point to (to be stable)
+impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
+ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+ ty::tls::with_opt(|tcx| {
+ trace!("hashing {:?}", *self);
+ let tcx = tcx.expect("can't hash AllocIds during hir lowering");
+ tcx.try_get_global_alloc(*self).hash_stable(hcx, hasher);
+ });
+ }
+}
+
+// `Relocations` with default type parameters is a sorted map.
+impl<'a, Prov> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Prov>
+where
+ Prov: HashStable<StableHashingContext<'a>>,
+{
+ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+ self.len().hash_stable(hcx, hasher);
+ for reloc in self.iter() {
+ reloc.hash_stable(hcx, hasher);
+ }
+ }
+}
+
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
+ type KeyType = region::Scope;
+
+ #[inline]
+ fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
+ *self
+ }
+}