]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/impls_ty.rs
Auto merge of #93717 - pietroalbini:pa-ci-profiler, r=Mark-Simulacrum
[rust.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 some very high number instead
90             // of their actual discriminant since `TyKind` should never start with anything
91             // that high.
92             ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
93             ty::subst::GenericArgKind::Const(ct) => {
94                 0xF3u8.hash_stable(hcx, hasher);
95                 ct.hash_stable(hcx, hasher);
96             }
97             ty::subst::GenericArgKind::Lifetime(lt) => {
98                 0xF5u8.hash_stable(hcx, hasher);
99                 lt.hash_stable(hcx, hasher);
100             }
101         }
102     }
103 }
104
105 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
106     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
107         mem::discriminant(self).hash_stable(hcx, hasher);
108         match *self {
109             ty::ReErased | ty::ReStatic => {
110                 // No variant fields to hash for these ...
111             }
112             ty::ReEmpty(universe) => {
113                 universe.hash_stable(hcx, hasher);
114             }
115             ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
116                 db.hash_stable(hcx, hasher);
117                 i.hash_stable(hcx, hasher);
118             }
119             ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
120                 db.hash_stable(hcx, hasher);
121                 def_id.hash_stable(hcx, hasher);
122                 name.hash_stable(hcx, hasher);
123             }
124             ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
125                 db.hash_stable(hcx, hasher);
126             }
127             ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
128                 def_id.hash_stable(hcx, hasher);
129                 index.hash_stable(hcx, hasher);
130                 name.hash_stable(hcx, hasher);
131             }
132             ty::ReFree(ref free_region) => {
133                 free_region.hash_stable(hcx, hasher);
134             }
135             ty::RePlaceholder(p) => {
136                 p.hash_stable(hcx, hasher);
137             }
138             ty::ReVar(reg) => {
139                 reg.hash_stable(hcx, hasher);
140             }
141         }
142     }
143 }
144
145 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
146     #[inline]
147     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
148         self.index().hash_stable(hcx, hasher);
149     }
150 }
151
152 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
153     #[inline]
154     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
155         self.index.hash_stable(hcx, hasher);
156     }
157 }
158
159 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
160     #[inline]
161     fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
162         self.index().hash_stable(hcx, hasher);
163     }
164 }
165
166 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<'tcx, T>
167 where
168     T: HashStable<StableHashingContext<'a>>,
169 {
170     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
171         self.as_ref().skip_binder().hash_stable(hcx, hasher);
172         self.bound_vars().hash_stable(hcx, hasher);
173     }
174 }
175
176 // AllocIds get resolved to whatever they point to (to be stable)
177 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
178     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
179         ty::tls::with_opt(|tcx| {
180             trace!("hashing {:?}", *self);
181             let tcx = tcx.expect("can't hash AllocIds during hir lowering");
182             tcx.get_global_alloc(*self).hash_stable(hcx, hasher);
183         });
184     }
185 }
186
187 // `Relocations` with default type parameters is a sorted map.
188 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
189 where
190     Tag: HashStable<StableHashingContext<'a>>,
191 {
192     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
193         self.len().hash_stable(hcx, hasher);
194         for reloc in self.iter() {
195             reloc.hash_stable(hcx, hasher);
196         }
197     }
198 }
199
200 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
201     type KeyType = region::Scope;
202
203     #[inline]
204     fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
205         *self
206     }
207 }