1 //! This module contains `HashStable` implementations for various data types
2 //! from `rustc_middle::ty` in no particular order.
4 use crate::middle::region;
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;
15 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
17 T: HashStable<StableHashingContext<'a>>,
19 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
21 static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
22 RefCell::new(Default::default());
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) {
31 let mut hasher = StableHasher::new();
32 (&self[..]).hash_stable(hcx, &mut hasher);
34 let hash: Fingerprint = hasher.finish();
35 cache.borrow_mut().insert(key, hash);
39 hash.hash_stable(hcx, hasher);
43 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
45 T: HashStable<StableHashingContext<'a>>,
47 type KeyType = Fingerprint;
50 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);
58 impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType {
59 type KeyType = Fingerprint;
62 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);
70 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
71 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
72 self.unpack().hash_stable(hcx, hasher);
76 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
77 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
79 // WARNING: We dedup cache the `HashStable` results for `List`
80 // while ignoring types and freely transmute
81 // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
82 // See `fn intern_type_list` for more details.
84 // We therefore hash types without adding a hash for their discriminant.
86 // In order to make it very unlikely for the sequence of bytes being hashed for
87 // a `GenericArgKind::Type` to be the same as the sequence of bytes being
88 // hashed for one of the other variants, we hash some very high number instead
89 // of their actual discriminant since `TyKind` should never start with anything
91 ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
92 ty::subst::GenericArgKind::Const(ct) => {
93 0xF3u8.hash_stable(hcx, hasher);
94 ct.hash_stable(hcx, hasher);
96 ty::subst::GenericArgKind::Lifetime(lt) => {
97 0xF5u8.hash_stable(hcx, hasher);
98 lt.hash_stable(hcx, hasher);
104 // AllocIds get resolved to whatever they point to (to be stable)
105 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
106 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
107 ty::tls::with_opt(|tcx| {
108 trace!("hashing {:?}", *self);
109 let tcx = tcx.expect("can't hash AllocIds during hir lowering");
110 tcx.try_get_global_alloc(*self).hash_stable(hcx, hasher);
115 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
116 type KeyType = region::Scope;
119 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {