1 //! This module contains `HashStable` implementations for various data types 2 //! from `rustc_middle::ty` in no particular order. 3 4 use crate::middle::region; 5 use crate::mir; 6 use crate::ty; 7 use crate::ty::fast_reject::SimplifiedType; 8 use rustc_data_structures::fingerprint::Fingerprint; 9 use rustc_data_structures::fx::FxHashMap; 10 use rustc_data_structures::stable_hasher::HashingControls; 11 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; 12 use rustc_query_system::ich::StableHashingContext; 13 use std::cell::RefCell; 14 15 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T> 16 where 17 T: HashStable<StableHashingContext<'a>>, 18 { hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher)19 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { 20 thread_local! { 21 static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> = 22 RefCell::new(Default::default()); 23 } 24 25 let hash = CACHE.with(|cache| { 26 let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls()); 27 if let Some(&hash) = cache.borrow().get(&key) { 28 return hash; 29 } 30 31 let mut hasher = StableHasher::new(); 32 (&self[..]).hash_stable(hcx, &mut hasher); 33 34 let hash: Fingerprint = hasher.finish(); 35 cache.borrow_mut().insert(key, hash); 36 hash 37 }); 38 39 hash.hash_stable(hcx, hasher); 40 } 41 } 42 43 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T> 44 where 45 T: HashStable<StableHashingContext<'a>>, 46 { 47 type KeyType = Fingerprint; 48 49 #[inline] to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint50 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint { 51 let mut hasher = StableHasher::new(); 52 let mut hcx: StableHashingContext<'a> = hcx.clone(); 53 self.hash_stable(&mut hcx, &mut hasher); 54 hasher.finish() 55 } 56 } 57 58 impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType { 59 type KeyType = Fingerprint; 60 61 #[inline] to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint62 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint { 63 let mut hasher = StableHasher::new(); 64 let mut hcx: StableHashingContext<'a> = hcx.clone(); 65 self.hash_stable(&mut hcx, &mut hasher); 66 hasher.finish() 67 } 68 } 69 70 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> { hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher)71 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { 72 self.unpack().hash_stable(hcx, hasher); 73 } 74 } 75 76 // AllocIds get resolved to whatever they point to (to be stable) 77 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId { hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher)78 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { 79 ty::tls::with_opt(|tcx| { 80 trace!("hashing {:?}", *self); 81 let tcx = tcx.expect("can't hash AllocIds during hir lowering"); 82 tcx.try_get_global_alloc(*self).hash_stable(hcx, hasher); 83 }); 84 } 85 } 86 87 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope { 88 type KeyType = region::Scope; 89 90 #[inline] to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope91 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope { 92 *self 93 } 94 } 95