diff options
Diffstat (limited to 'src/librustc_middle/ich/impls_ty.rs')
| -rw-r--r-- | src/librustc_middle/ich/impls_ty.rs | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/librustc_middle/ich/impls_ty.rs b/src/librustc_middle/ich/impls_ty.rs new file mode 100644 index 00000000000..377c8661cbd --- /dev/null +++ b/src/librustc_middle/ich/impls_ty.rs @@ -0,0 +1,207 @@ +//! This module contains `HashStable` implementations for various data types +//! from `rustc_middle::ty` in no particular order. + +use crate::ich::{NodeIdHashingMode, StableHashingContext}; +use crate::middle::region; +use crate::mir; +use crate::ty; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use std::cell::RefCell; +use std::mem; + +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), Fingerprint>> = + RefCell::new(Default::default()); + } + + let hash = CACHE.with(|cache| { + let key = (self.as_ptr() as usize, self.len()); + 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, '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> HashStable<StableHashingContext<'a>> for ty::RegionKind { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + ty::ReErased | ty::ReStatic => { + // No variant fields to hash for these ... + } + ty::ReEmpty(universe) => { + universe.hash_stable(hcx, hasher); + } + ty::ReLateBound(db, ty::BrAnon(i)) => { + db.hash_stable(hcx, hasher); + i.hash_stable(hcx, hasher); + } + ty::ReLateBound(db, ty::BrNamed(def_id, name)) => { + db.hash_stable(hcx, hasher); + def_id.hash_stable(hcx, hasher); + name.hash_stable(hcx, hasher); + } + ty::ReLateBound(db, ty::BrEnv) => { + db.hash_stable(hcx, hasher); + } + ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => { + def_id.hash_stable(hcx, hasher); + index.hash_stable(hcx, hasher); + name.hash_stable(hcx, hasher); + } + ty::ReScope(scope) => { + scope.hash_stable(hcx, hasher); + } + ty::ReFree(ref free_region) => { + free_region.hash_stable(hcx, hasher); + } + ty::ReVar(..) | ty::RePlaceholder(..) => { + bug!("StableHasher: unexpected region {:?}", *self) + } + } + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid { + #[inline] + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.index().hash_stable(hcx, hasher); + } +} + +impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> { + #[inline] + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.index.hash_stable(hcx, hasher); + } +} + +impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar { + #[inline] + fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + self.index().hash_stable(hcx, hasher); + } +} + +impl<'a, T> HashStable<StableHashingContext<'a>> for ty::Binder<T> +where + T: HashStable<StableHashingContext<'a>>, +{ + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.skip_binder().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.get_global_alloc(*self).hash_stable(hcx, hasher); + }); + } +} + +// `Relocations` with default type parameters is a sorted map. +impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag> +where + Tag: 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 + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for ty::TyVid { + fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { + // `TyVid` values are confined to an inference context and hence + // should not be hashed. + bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self) + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for ty::IntVid { + fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { + // `IntVid` values are confined to an inference context and hence + // should not be hashed. + bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self) + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for ty::FloatVid { + fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { + // `FloatVid` values are confined to an inference context and hence + // should not be hashed. + bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self) + } +} + +impl<'a, T> HashStable<StableHashingContext<'a>> for ty::steal::Steal<T> +where + T: HashStable<StableHashingContext<'a>>, +{ + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.borrow().hash_stable(hcx, hasher); + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::privacy::AccessLevels { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let crate::middle::privacy::AccessLevels { ref map } = *self; + + map.hash_stable(hcx, hasher); + }); + } +} |
