]> git.lizzy.rs Git - rust.git/blob - src/librustc/ich/impls_hir.rs
merge item id stable hashing functions
[rust.git] / src / librustc / ich / impls_hir.rs
1 //! This module contains `HashStable` implementations for various HIR data
2 //! types in no particular order.
3
4 use crate::hir::map::DefPathHash;
5 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
6 use rustc_attr as attr;
7 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
8 use rustc_hir as hir;
9 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
10 use smallvec::SmallVec;
11 use std::mem;
12
13 impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
14     #[inline]
15     fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) {
16         let hcx = self;
17         hcx.def_path_hash(def_id).hash_stable(hcx, hasher);
18     }
19
20     #[inline]
21     fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) {
22         let hcx = self;
23         match hcx.node_id_hashing_mode {
24             NodeIdHashingMode::Ignore => {
25                 // Don't do anything.
26             }
27             NodeIdHashingMode::HashDefPath => {
28                 let hir::HirId { owner, local_id } = hir_id;
29
30                 hcx.local_def_path_hash(owner).hash_stable(hcx, hasher);
31                 local_id.hash_stable(hcx, hasher);
32             }
33         }
34     }
35
36     fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) {
37         let hcx = self;
38         if hcx.hash_bodies() {
39             hcx.body_resolver.body(id).hash_stable(hcx, hasher);
40         }
41     }
42
43     // The following implementations of HashStable for `ItemId`, `TraitItemId`, and
44     // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
45     // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
46     // are used when another item in the HIR is *referenced* and we certainly
47     // want to pick up on a reference changing its target, so we hash the NodeIds
48     // in "DefPath Mode".
49
50     fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) {
51         let hcx = self;
52
53         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
54             id.hash_stable(hcx, hasher);
55         })
56     }
57
58     fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) {
59         let hcx = self;
60         let hir::Mod { inner: ref inner_span, ref item_ids } = *module;
61
62         inner_span.hash_stable(hcx, hasher);
63
64         // Combining the `DefPathHash`s directly is faster than feeding them
65         // into the hasher. Because we use a commutative combine, we also don't
66         // have to sort the array.
67         let item_ids_hash = item_ids
68             .iter()
69             .map(|id| {
70                 let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
71                 debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0));
72                 def_path_hash.0
73             })
74             .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b));
75
76         item_ids.len().hash_stable(hcx, hasher);
77         item_ids_hash.hash_stable(hcx, hasher);
78     }
79
80     fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) {
81         self.while_hashing_hir_bodies(true, |hcx| {
82             let hir::Expr { hir_id: _, ref span, ref kind, ref attrs } = *expr;
83
84             span.hash_stable(hcx, hasher);
85             kind.hash_stable(hcx, hasher);
86             attrs.hash_stable(hcx, hasher);
87         })
88     }
89
90     fn hash_hir_ty(&mut self, ty: &hir::Ty<'_>, hasher: &mut StableHasher) {
91         self.while_hashing_hir_bodies(true, |hcx| {
92             let hir::Ty { hir_id: _, ref kind, ref span } = *ty;
93
94             kind.hash_stable(hcx, hasher);
95             span.hash_stable(hcx, hasher);
96         })
97     }
98
99     fn hash_hir_visibility_kind(
100         &mut self,
101         vis: &hir::VisibilityKind<'_>,
102         hasher: &mut StableHasher,
103     ) {
104         let hcx = self;
105         mem::discriminant(vis).hash_stable(hcx, hasher);
106         match *vis {
107             hir::VisibilityKind::Public | hir::VisibilityKind::Inherited => {
108                 // No fields to hash.
109             }
110             hir::VisibilityKind::Crate(sugar) => {
111                 sugar.hash_stable(hcx, hasher);
112             }
113             hir::VisibilityKind::Restricted { ref path, hir_id } => {
114                 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
115                     hir_id.hash_stable(hcx, hasher);
116                 });
117                 path.hash_stable(hcx, hasher);
118             }
119         }
120     }
121 }
122
123 impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
124     type KeyType = DefPathHash;
125
126     #[inline]
127     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
128         hcx.def_path_hash(*self)
129     }
130 }
131
132 impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
133     #[inline]
134     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
135         hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
136     }
137 }
138
139 impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
140     type KeyType = DefPathHash;
141
142     #[inline]
143     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
144         hcx.def_path_hash(self.to_def_id())
145     }
146 }
147
148 impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
149     #[inline]
150     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
151         hcx.def_path_hash(DefId { krate: *self, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher);
152     }
153 }
154
155 impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
156     type KeyType = DefPathHash;
157
158     #[inline]
159     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
160         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
161         def_id.to_stable_hash_key(hcx)
162     }
163 }
164
165 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::ItemLocalId {
166     type KeyType = hir::ItemLocalId;
167
168     #[inline]
169     fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> hir::ItemLocalId {
170         *self
171     }
172 }
173
174 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem<'_> {
175     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
176         let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
177
178         hcx.hash_hir_item_like(|hcx| {
179             ident.name.hash_stable(hcx, hasher);
180             attrs.hash_stable(hcx, hasher);
181             generics.hash_stable(hcx, hasher);
182             kind.hash_stable(hcx, hasher);
183             span.hash_stable(hcx, hasher);
184         });
185     }
186 }
187
188 impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem<'_> {
189     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
190         let hir::ImplItem {
191             hir_id: _,
192             ident,
193             ref vis,
194             defaultness,
195             ref attrs,
196             ref generics,
197             ref kind,
198             span,
199         } = *self;
200
201         hcx.hash_hir_item_like(|hcx| {
202             ident.name.hash_stable(hcx, hasher);
203             vis.hash_stable(hcx, hasher);
204             defaultness.hash_stable(hcx, hasher);
205             attrs.hash_stable(hcx, hasher);
206             generics.hash_stable(hcx, hasher);
207             kind.hash_stable(hcx, hasher);
208             span.hash_stable(hcx, hasher);
209         });
210     }
211 }
212
213 impl<'a> HashStable<StableHashingContext<'a>> for hir::Item<'_> {
214     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
215         let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
216
217         hcx.hash_hir_item_like(|hcx| {
218             ident.name.hash_stable(hcx, hasher);
219             attrs.hash_stable(hcx, hasher);
220             kind.hash_stable(hcx, hasher);
221             vis.hash_stable(hcx, hasher);
222             span.hash_stable(hcx, hasher);
223         });
224     }
225 }
226
227 impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> {
228     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
229         let hir::Body { params, value, generator_kind } = self;
230
231         hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
232             params.hash_stable(hcx, hasher);
233             value.hash_stable(hcx, hasher);
234             generator_kind.hash_stable(hcx, hasher);
235         });
236     }
237 }
238
239 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
240     type KeyType = (DefPathHash, hir::ItemLocalId);
241
242     #[inline]
243     fn to_stable_hash_key(
244         &self,
245         hcx: &StableHashingContext<'a>,
246     ) -> (DefPathHash, hir::ItemLocalId) {
247         let hir::BodyId { hir_id } = *self;
248         hir_id.to_stable_hash_key(hcx)
249     }
250 }
251
252 impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {
253     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
254         hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
255     }
256 }
257
258 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex {
259     type KeyType = DefPathHash;
260
261     #[inline]
262     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
263         hcx.local_def_path_hash(*self)
264     }
265 }
266
267 impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::lang_items::LangItem {
268     fn hash_stable(&self, _: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
269         ::std::hash::Hash::hash(self, hasher);
270     }
271 }
272
273 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
274     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
275         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
276             let hir::TraitCandidate { def_id, import_ids } = self;
277
278             def_id.hash_stable(hcx, hasher);
279             import_ids.hash_stable(hcx, hasher);
280         });
281     }
282 }
283
284 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
285     type KeyType = (DefPathHash, SmallVec<[(DefPathHash, hir::ItemLocalId); 1]>);
286
287     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType {
288         let hir::TraitCandidate { def_id, import_ids } = self;
289
290         let import_keys = import_ids
291             .iter()
292             .map(|node_id| hcx.node_to_hir_id(*node_id))
293             .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id))
294             .collect();
295         (hcx.def_path_hash(*def_id), import_keys)
296     }
297 }
298
299 impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
300     fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
301         mem::discriminant(self).hash_stable(hcx, hasher);
302     }
303 }
304
305 impl<'hir> HashStable<StableHashingContext<'hir>> for attr::OptimizeAttr {
306     fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
307         mem::discriminant(self).hash_stable(hcx, hasher);
308     }
309 }