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