1 //! This module contains `HashStable` implementations for various data types
2 //! from rustc::ty in no particular order.
4 use crate::ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
7 StableHasher, StableHasherResult};
8 use std::cell::RefCell;
10 use crate::middle::region;
14 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
16 where T: HashStable<StableHashingContext<'a>> {
17 fn hash_stable<W: StableHasherResult>(&self,
18 hcx: &mut StableHashingContext<'a>,
19 hasher: &mut StableHasher<W>) {
21 static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
22 RefCell::new(Default::default());
25 let hash = CACHE.with(|cache| {
26 let key = (self.as_ptr() as usize, self.len());
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, 'gcx, T> ToStableHashKey<StableHashingContext<'a>> for &'gcx ty::List<T>
44 where T: HashStable<StableHashingContext<'a>>
46 type KeyType = Fingerprint;
49 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
50 let mut hasher = StableHasher::new();
51 let mut hcx: StableHashingContext<'a> = hcx.clone();
52 self.hash_stable(&mut hcx, &mut hasher);
57 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::subst::Kind<'gcx> {
58 fn hash_stable<W: StableHasherResult>(&self,
59 hcx: &mut StableHashingContext<'a>,
60 hasher: &mut StableHasher<W>) {
61 self.unpack().hash_stable(hcx, hasher);
65 impl<'a> HashStable<StableHashingContext<'a>>
67 fn hash_stable<W: StableHasherResult>(&self,
68 hcx: &mut StableHashingContext<'a>,
69 hasher: &mut StableHasher<W>) {
70 mem::discriminant(self).hash_stable(hcx, hasher);
75 // No variant fields to hash for these ...
77 ty::ReLateBound(db, ty::BrAnon(i)) => {
78 db.hash_stable(hcx, hasher);
79 i.hash_stable(hcx, hasher);
81 ty::ReLateBound(db, ty::BrNamed(def_id, name)) => {
82 db.hash_stable(hcx, hasher);
83 def_id.hash_stable(hcx, hasher);
84 name.hash_stable(hcx, hasher);
86 ty::ReLateBound(db, ty::BrEnv) => {
87 db.hash_stable(hcx, hasher);
89 ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
90 def_id.hash_stable(hcx, hasher);
91 index.hash_stable(hcx, hasher);
92 name.hash_stable(hcx, hasher);
94 ty::ReScope(scope) => {
95 scope.hash_stable(hcx, hasher);
97 ty::ReFree(ref free_region) => {
98 free_region.hash_stable(hcx, hasher);
100 ty::ReClosureBound(vid) => {
101 vid.hash_stable(hcx, hasher);
104 ty::RePlaceholder(..) => {
105 bug!("StableHasher: unexpected region {:?}", *self)
111 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
113 fn hash_stable<W: StableHasherResult>(&self,
114 hcx: &mut StableHashingContext<'a>,
115 hasher: &mut StableHasher<W>) {
116 self.index().hash_stable(hcx, hasher);
120 impl<'gcx, 'tcx> HashStable<StableHashingContext<'gcx>> for ty::ConstVid<'tcx> {
122 fn hash_stable<W: StableHasherResult>(&self,
123 hcx: &mut StableHashingContext<'gcx>,
124 hasher: &mut StableHasher<W>) {
125 self.index.hash_stable(hcx, hasher);
129 impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
131 fn hash_stable<W: StableHasherResult>(&self,
132 hcx: &mut StableHashingContext<'gcx>,
133 hasher: &mut StableHasher<W>) {
134 self.index().hash_stable(hcx, hasher);
138 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<T>
139 where T: HashStable<StableHashingContext<'a>>
141 fn hash_stable<W: StableHasherResult>(&self,
142 hcx: &mut StableHashingContext<'a>,
143 hasher: &mut StableHasher<W>) {
144 self.skip_binder().hash_stable(hcx, hasher);
148 // AllocIds get resolved to whatever they point to (to be stable)
149 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
150 fn hash_stable<W: StableHasherResult>(
152 hcx: &mut StableHashingContext<'a>,
153 hasher: &mut StableHasher<W>,
155 ty::tls::with_opt(|tcx| {
156 trace!("hashing {:?}", *self);
157 let tcx = tcx.expect("can't hash AllocIds during hir lowering");
158 let alloc_kind = tcx.alloc_map.lock().get(*self);
159 alloc_kind.hash_stable(hcx, hasher);
164 // Allocations treat their relocations specially
165 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::Allocation {
166 fn hash_stable<W: StableHasherResult>(
168 hcx: &mut StableHashingContext<'a>,
169 hasher: &mut StableHasher<W>,
171 self.bytes.hash_stable(hcx, hasher);
172 for reloc in self.relocations.iter() {
173 reloc.hash_stable(hcx, hasher);
175 self.undef_mask.hash_stable(hcx, hasher);
176 self.align.hash_stable(hcx, hasher);
177 self.mutability.hash_stable(hcx, hasher);
181 impl_stable_hash_for!(enum ::syntax::ast::Mutability {
186 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
187 type KeyType = region::Scope;
190 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
195 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
198 fn hash_stable<W: StableHasherResult>(&self,
199 _hcx: &mut StableHashingContext<'a>,
200 _hasher: &mut StableHasher<W>) {
201 // TyVid values are confined to an inference context and hence
202 // should not be hashed.
203 bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self)
207 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
210 fn hash_stable<W: StableHasherResult>(&self,
211 _hcx: &mut StableHashingContext<'a>,
212 _hasher: &mut StableHasher<W>) {
213 // IntVid values are confined to an inference context and hence
214 // should not be hashed.
215 bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self)
219 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
222 fn hash_stable<W: StableHasherResult>(&self,
223 _hcx: &mut StableHashingContext<'a>,
224 _hasher: &mut StableHasher<W>) {
225 // FloatVid values are confined to an inference context and hence
226 // should not be hashed.
227 bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self)
231 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
232 for ty::steal::Steal<T>
233 where T: HashStable<StableHashingContext<'a>>
235 fn hash_stable<W: StableHasherResult>(&self,
236 hcx: &mut StableHashingContext<'a>,
237 hasher: &mut StableHasher<W>) {
238 self.borrow().hash_stable(hcx, hasher);
242 impl<'a> HashStable<StableHashingContext<'a>>
243 for crate::middle::privacy::AccessLevels {
244 fn hash_stable<W: StableHasherResult>(&self,
245 hcx: &mut StableHashingContext<'a>,
246 hasher: &mut StableHasher<W>) {
247 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
248 let crate::middle::privacy::AccessLevels {
252 map.hash_stable(hcx, hasher);