]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/ty/impls_ty.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / impls_ty.rs
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 use std::mem;
15
16 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
17 where
18 T: HashStable<StableHashingContext<'a>>,
19 {
20 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
21 thread_local! {
22 static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
23 RefCell::new(Default::default());
24 }
25
26 let hash = CACHE.with(|cache| {
27 let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls());
28 if let Some(&hash) = cache.borrow().get(&key) {
29 return hash;
30 }
31
32 let mut hasher = StableHasher::new();
33 (&self[..]).hash_stable(hcx, &mut hasher);
34
35 let hash: Fingerprint = hasher.finish();
36 cache.borrow_mut().insert(key, hash);
37 hash
38 });
39
40 hash.hash_stable(hcx, hasher);
41 }
42 }
43
44 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
45 where
46 T: HashStable<StableHashingContext<'a>>,
47 {
48 type KeyType = Fingerprint;
49
50 #[inline]
51 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
52 let mut hasher = StableHasher::new();
53 let mut hcx: StableHashingContext<'a> = hcx.clone();
54 self.hash_stable(&mut hcx, &mut hasher);
55 hasher.finish()
56 }
57 }
58
59 impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType {
60 type KeyType = Fingerprint;
61
62 #[inline]
63 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
64 let mut hasher = StableHasher::new();
65 let mut hcx: StableHashingContext<'a> = hcx.clone();
66 self.hash_stable(&mut hcx, &mut hasher);
67 hasher.finish()
68 }
69 }
70
71 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
72 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
73 self.unpack().hash_stable(hcx, hasher);
74 }
75 }
76
77 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
78 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
79 match self {
80 // WARNING: We dedup cache the `HashStable` results for `List`
81 // while ignoring types and freely transmute
82 // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
83 // See `fn intern_type_list` for more details.
84 //
85 // We therefore hash types without adding a hash for their discriminant.
86 //
87 // In order to make it very unlikely for the sequence of bytes being hashed for
88 // a `GenericArgKind::Type` to be the same as the sequence of bytes being
89 // hashed for one of the other variants, we hash a `0xFF` byte before hashing
90 // their discriminant (since the discriminant of `TyKind` is unlikely to ever start
91 // with 0xFF).
92 ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
93 ty::subst::GenericArgKind::Const(ct) => {
94 0xFFu8.hash_stable(hcx, hasher);
95 mem::discriminant(self).hash_stable(hcx, hasher);
96 ct.hash_stable(hcx, hasher);
97 }
98 ty::subst::GenericArgKind::Lifetime(lt) => {
99 0xFFu8.hash_stable(hcx, hasher);
100 mem::discriminant(self).hash_stable(hcx, hasher);
101 lt.hash_stable(hcx, hasher);
102 }
103 }
104 }
105 }
106
107 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
108 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
109 mem::discriminant(self).hash_stable(hcx, hasher);
110 match *self {
111 ty::ReErased | ty::ReStatic => {
112 // No variant fields to hash for these ...
113 }
114 ty::ReEmpty(universe) => {
115 universe.hash_stable(hcx, hasher);
116 }
117 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
118 db.hash_stable(hcx, hasher);
119 i.hash_stable(hcx, hasher);
120 }
121 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
122 db.hash_stable(hcx, hasher);
123 def_id.hash_stable(hcx, hasher);
124 name.hash_stable(hcx, hasher);
125 }
126 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
127 db.hash_stable(hcx, hasher);
128 }
129 ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
130 def_id.hash_stable(hcx, hasher);
131 index.hash_stable(hcx, hasher);
132 name.hash_stable(hcx, hasher);
133 }
134 ty::ReFree(ref free_region) => {
135 free_region.hash_stable(hcx, hasher);
136 }
137 ty::RePlaceholder(p) => {
138 p.hash_stable(hcx, hasher);
139 }
140 ty::ReVar(..) => {
141 bug!("StableHasher: unexpected region {:?}", *self)
142 }
143 }
144 }
145 }
146
147 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
148 #[inline]
149 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
150 self.index().hash_stable(hcx, hasher);
151 }
152 }
153
154 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
155 #[inline]
156 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
157 self.index.hash_stable(hcx, hasher);
158 }
159 }
160
161 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
162 #[inline]
163 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
164 self.index().hash_stable(hcx, hasher);
165 }
166 }
167
168 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<'tcx, T>
169 where
170 T: HashStable<StableHashingContext<'a>>,
171 {
172 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
173 self.as_ref().skip_binder().hash_stable(hcx, hasher);
174 self.bound_vars().hash_stable(hcx, hasher);
175 }
176 }
177
178 // AllocIds get resolved to whatever they point to (to be stable)
179 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
180 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
181 ty::tls::with_opt(|tcx| {
182 trace!("hashing {:?}", *self);
183 let tcx = tcx.expect("can't hash AllocIds during hir lowering");
184 tcx.get_global_alloc(*self).hash_stable(hcx, hasher);
185 });
186 }
187 }
188
189 // `Relocations` with default type parameters is a sorted map.
190 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
191 where
192 Tag: HashStable<StableHashingContext<'a>>,
193 {
194 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
195 self.len().hash_stable(hcx, hasher);
196 for reloc in self.iter() {
197 reloc.hash_stable(hcx, hasher);
198 }
199 }
200 }
201
202 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
203 type KeyType = region::Scope;
204
205 #[inline]
206 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
207 *self
208 }
209 }