1 //! This module contains `HashStable` implementations for various data types
2 //! from rustc::ty in no particular order.
4 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
5 use crate::middle::region;
8 use rustc_data_structures::fx::FxHashMap;
9 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
10 use std::cell::RefCell;
13 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
15 T: HashStable<StableHashingContext<'a>>,
17 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
19 static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
20 RefCell::new(Default::default());
23 let hash = CACHE.with(|cache| {
24 let key = (self.as_ptr() as usize, self.len());
25 if let Some(&hash) = cache.borrow().get(&key) {
29 let mut hasher = StableHasher::new();
30 (&self[..]).hash_stable(hcx, &mut hasher);
32 let hash: Fingerprint = hasher.finish();
33 cache.borrow_mut().insert(key, hash);
37 hash.hash_stable(hcx, hasher);
41 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
43 T: HashStable<StableHashingContext<'a>>,
45 type KeyType = Fingerprint;
48 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
49 let mut hasher = StableHasher::new();
50 let mut hcx: StableHashingContext<'a> = hcx.clone();
51 self.hash_stable(&mut hcx, &mut hasher);
56 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
57 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
58 self.unpack().hash_stable(hcx, hasher);
62 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
63 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
64 mem::discriminant(self).hash_stable(hcx, hasher);
66 ty::ReErased | ty::ReStatic | ty::ReEmpty => {
67 // No variant fields to hash for these ...
69 ty::ReLateBound(db, ty::BrAnon(i)) => {
70 db.hash_stable(hcx, hasher);
71 i.hash_stable(hcx, hasher);
73 ty::ReLateBound(db, ty::BrNamed(def_id, name)) => {
74 db.hash_stable(hcx, hasher);
75 def_id.hash_stable(hcx, hasher);
76 name.hash_stable(hcx, hasher);
78 ty::ReLateBound(db, ty::BrEnv) => {
79 db.hash_stable(hcx, hasher);
81 ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
82 def_id.hash_stable(hcx, hasher);
83 index.hash_stable(hcx, hasher);
84 name.hash_stable(hcx, hasher);
86 ty::ReScope(scope) => {
87 scope.hash_stable(hcx, hasher);
89 ty::ReFree(ref free_region) => {
90 free_region.hash_stable(hcx, hasher);
92 ty::ReClosureBound(vid) => {
93 vid.hash_stable(hcx, hasher);
95 ty::ReVar(..) | ty::RePlaceholder(..) => {
96 bug!("StableHasher: unexpected region {:?}", *self)
102 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
104 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
105 self.index().hash_stable(hcx, hasher);
109 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
111 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
112 self.index.hash_stable(hcx, hasher);
116 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
118 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
119 self.index().hash_stable(hcx, hasher);
123 impl<'a, T> HashStable<StableHashingContext<'a>> for ty::Binder<T>
125 T: HashStable<StableHashingContext<'a>>,
127 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
128 self.skip_binder().hash_stable(hcx, hasher);
132 // AllocIds get resolved to whatever they point to (to be stable)
133 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
134 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
135 ty::tls::with_opt(|tcx| {
136 trace!("hashing {:?}", *self);
137 let tcx = tcx.expect("can't hash AllocIds during hir lowering");
138 let alloc_kind = tcx.alloc_map.lock().get(*self);
139 alloc_kind.hash_stable(hcx, hasher);
144 // `Relocations` with default type parameters is a sorted map.
145 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
147 Tag: HashStable<StableHashingContext<'a>>,
149 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
150 self.len().hash_stable(hcx, hasher);
151 for reloc in self.iter() {
152 reloc.hash_stable(hcx, hasher);
157 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
158 type KeyType = region::Scope;
161 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
166 impl<'a> HashStable<StableHashingContext<'a>> for ty::TyVid {
167 fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) {
168 // `TyVid` values are confined to an inference context and hence
169 // should not be hashed.
170 bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self)
174 impl<'a> HashStable<StableHashingContext<'a>> for ty::IntVid {
175 fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) {
176 // `IntVid` values are confined to an inference context and hence
177 // should not be hashed.
178 bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self)
182 impl<'a> HashStable<StableHashingContext<'a>> for ty::FloatVid {
183 fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) {
184 // `FloatVid` values are confined to an inference context and hence
185 // should not be hashed.
186 bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self)
190 impl<'a, T> HashStable<StableHashingContext<'a>> for ty::steal::Steal<T>
192 T: HashStable<StableHashingContext<'a>>,
194 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
195 self.borrow().hash_stable(hcx, hasher);
199 impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::privacy::AccessLevels {
200 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
201 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
202 let crate::middle::privacy::AccessLevels { ref map } = *self;
204 map.hash_stable(hcx, hasher);