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);
103 ty::ReLateBound(..) |
105 ty::RePlaceholder(..) => {
106 bug!("StableHasher: unexpected region {:?}", *self)
112 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
114 fn hash_stable<W: StableHasherResult>(&self,
115 hcx: &mut StableHashingContext<'a>,
116 hasher: &mut StableHasher<W>) {
117 self.index().hash_stable(hcx, hasher);
121 impl<'gcx, 'tcx> HashStable<StableHashingContext<'gcx>> for ty::ConstVid<'tcx> {
123 fn hash_stable<W: StableHasherResult>(&self,
124 hcx: &mut StableHashingContext<'gcx>,
125 hasher: &mut StableHasher<W>) {
126 self.index.hash_stable(hcx, hasher);
130 impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
132 fn hash_stable<W: StableHasherResult>(&self,
133 hcx: &mut StableHashingContext<'gcx>,
134 hasher: &mut StableHasher<W>) {
135 self.index().hash_stable(hcx, hasher);
139 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<T>
140 where T: HashStable<StableHashingContext<'a>>
142 fn hash_stable<W: StableHasherResult>(&self,
143 hcx: &mut StableHashingContext<'a>,
144 hasher: &mut StableHasher<W>) {
145 self.skip_binder().hash_stable(hcx, hasher);
149 // AllocIds get resolved to whatever they point to (to be stable)
150 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
151 fn hash_stable<W: StableHasherResult>(
153 hcx: &mut StableHashingContext<'a>,
154 hasher: &mut StableHasher<W>,
156 ty::tls::with_opt(|tcx| {
157 trace!("hashing {:?}", *self);
158 let tcx = tcx.expect("can't hash AllocIds during hir lowering");
159 let alloc_kind = tcx.alloc_map.lock().get(*self);
160 alloc_kind.hash_stable(hcx, hasher);
165 // Allocations treat their relocations specially
166 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::Allocation {
167 fn hash_stable<W: StableHasherResult>(
169 hcx: &mut StableHashingContext<'a>,
170 hasher: &mut StableHasher<W>,
172 self.bytes.hash_stable(hcx, hasher);
173 for reloc in self.relocations.iter() {
174 reloc.hash_stable(hcx, hasher);
176 self.undef_mask.hash_stable(hcx, hasher);
177 self.align.hash_stable(hcx, hasher);
178 self.mutability.hash_stable(hcx, hasher);
182 impl_stable_hash_for!(enum ::syntax::ast::Mutability {
187 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
188 type KeyType = region::Scope;
191 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
196 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
199 fn hash_stable<W: StableHasherResult>(&self,
200 _hcx: &mut StableHashingContext<'a>,
201 _hasher: &mut StableHasher<W>) {
202 // TyVid values are confined to an inference context and hence
203 // should not be hashed.
204 bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self)
208 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
211 fn hash_stable<W: StableHasherResult>(&self,
212 _hcx: &mut StableHashingContext<'a>,
213 _hasher: &mut StableHasher<W>) {
214 // IntVid values are confined to an inference context and hence
215 // should not be hashed.
216 bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self)
220 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
223 fn hash_stable<W: StableHasherResult>(&self,
224 _hcx: &mut StableHashingContext<'a>,
225 _hasher: &mut StableHasher<W>) {
226 // FloatVid values are confined to an inference context and hence
227 // should not be hashed.
228 bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self)
232 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
233 for ty::steal::Steal<T>
234 where T: HashStable<StableHashingContext<'a>>
236 fn hash_stable<W: StableHasherResult>(&self,
237 hcx: &mut StableHashingContext<'a>,
238 hasher: &mut StableHasher<W>) {
239 self.borrow().hash_stable(hcx, hasher);
243 impl<'a> HashStable<StableHashingContext<'a>>
244 for crate::middle::privacy::AccessLevels {
245 fn hash_stable<W: StableHasherResult>(&self,
246 hcx: &mut StableHashingContext<'a>,
247 hasher: &mut StableHasher<W>) {
248 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
249 let crate::middle::privacy::AccessLevels {
253 map.hash_stable(hcx, hasher);