1 //! This module contains `HashStable` implementations for various HIR data
2 //! types in no particular order.
5 use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
6 use crate::hir::map::DefPathHash;
7 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
9 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
10 use smallvec::SmallVec;
14 impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
16 fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) {
18 hcx.def_path_hash(def_id).hash_stable(hcx, hasher);
22 fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) {
24 match hcx.node_id_hashing_mode {
25 NodeIdHashingMode::Ignore => {
28 NodeIdHashingMode::HashDefPath => {
29 let hir::HirId { owner, local_id } = hir_id;
31 hcx.local_def_path_hash(owner).hash_stable(hcx, hasher);
32 local_id.hash_stable(hcx, hasher);
37 fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) {
39 if hcx.hash_bodies() {
40 hcx.body_resolver.body(id).hash_stable(hcx, hasher);
44 // The following implementations of HashStable for `ItemId`, `TraitItemId`, and
45 // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
46 // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
47 // are used when another item in the HIR is *referenced* and we certainly
48 // want to pick up on a reference changing its target, so we hash the NodeIds
51 fn hash_item_id(&mut self, id: hir::ItemId, hasher: &mut StableHasher) {
53 let hir::ItemId { id } = id;
55 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
56 id.hash_stable(hcx, hasher);
60 fn hash_impl_item_id(&mut self, id: hir::ImplItemId, hasher: &mut StableHasher) {
62 let hir::ImplItemId { hir_id } = id;
64 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
65 hir_id.hash_stable(hcx, hasher);
69 fn hash_trait_item_id(&mut self, id: hir::TraitItemId, hasher: &mut StableHasher) {
71 let hir::TraitItemId { hir_id } = id;
73 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
74 hir_id.hash_stable(hcx, hasher);
78 fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) {
80 let hir::Mod { inner: ref inner_span, ref item_ids } = *module;
82 inner_span.hash_stable(hcx, hasher);
84 // Combining the `DefPathHash`s directly is faster than feeding them
85 // into the hasher. Because we use a commutative combine, we also don't
86 // have to sort the array.
87 let item_ids_hash = item_ids
90 let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
91 debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0));
94 .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b));
96 item_ids.len().hash_stable(hcx, hasher);
97 item_ids_hash.hash_stable(hcx, hasher);
100 fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) {
101 self.while_hashing_hir_bodies(true, |hcx| {
102 let hir::Expr { hir_id: _, ref span, ref kind, ref attrs } = *expr;
104 span.hash_stable(hcx, hasher);
105 kind.hash_stable(hcx, hasher);
106 attrs.hash_stable(hcx, hasher);
110 fn hash_hir_ty(&mut self, ty: &hir::Ty<'_>, hasher: &mut StableHasher) {
111 self.while_hashing_hir_bodies(true, |hcx| {
112 let hir::Ty { hir_id: _, ref kind, ref span } = *ty;
114 kind.hash_stable(hcx, hasher);
115 span.hash_stable(hcx, hasher);
119 fn hash_hir_visibility_kind(
121 vis: &hir::VisibilityKind<'_>,
122 hasher: &mut StableHasher,
125 mem::discriminant(vis).hash_stable(hcx, hasher);
127 hir::VisibilityKind::Public | hir::VisibilityKind::Inherited => {
128 // No fields to hash.
130 hir::VisibilityKind::Crate(sugar) => {
131 sugar.hash_stable(hcx, hasher);
133 hir::VisibilityKind::Restricted { ref path, hir_id } => {
134 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
135 hir_id.hash_stable(hcx, hasher);
137 path.hash_stable(hcx, hasher);
143 impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
144 type KeyType = DefPathHash;
147 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
148 hcx.def_path_hash(*self)
152 impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
154 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
155 hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
159 impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
160 type KeyType = DefPathHash;
163 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
164 hcx.def_path_hash(self.to_def_id())
168 impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
170 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
171 hcx.def_path_hash(DefId { krate: *self, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher);
175 impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
176 type KeyType = DefPathHash;
179 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
180 let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
181 def_id.to_stable_hash_key(hcx)
185 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::ItemLocalId {
186 type KeyType = hir::ItemLocalId;
189 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> hir::ItemLocalId {
194 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem<'_> {
195 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
196 let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
198 hcx.hash_hir_item_like(|hcx| {
199 ident.name.hash_stable(hcx, hasher);
200 attrs.hash_stable(hcx, hasher);
201 generics.hash_stable(hcx, hasher);
202 kind.hash_stable(hcx, hasher);
203 span.hash_stable(hcx, hasher);
208 impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem<'_> {
209 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
221 hcx.hash_hir_item_like(|hcx| {
222 ident.name.hash_stable(hcx, hasher);
223 vis.hash_stable(hcx, hasher);
224 defaultness.hash_stable(hcx, hasher);
225 attrs.hash_stable(hcx, hasher);
226 generics.hash_stable(hcx, hasher);
227 kind.hash_stable(hcx, hasher);
228 span.hash_stable(hcx, hasher);
233 impl<'a> HashStable<StableHashingContext<'a>> for hir::Item<'_> {
234 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
235 let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
237 hcx.hash_hir_item_like(|hcx| {
238 ident.name.hash_stable(hcx, hasher);
239 attrs.hash_stable(hcx, hasher);
240 kind.hash_stable(hcx, hasher);
241 vis.hash_stable(hcx, hasher);
242 span.hash_stable(hcx, hasher);
247 impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> {
248 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
249 let hir::Body { params, value, generator_kind } = self;
251 hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
252 params.hash_stable(hcx, hasher);
253 value.hash_stable(hcx, hasher);
254 generator_kind.hash_stable(hcx, hasher);
259 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
260 type KeyType = (DefPathHash, hir::ItemLocalId);
263 fn to_stable_hash_key(
265 hcx: &StableHashingContext<'a>,
266 ) -> (DefPathHash, hir::ItemLocalId) {
267 let hir::BodyId { hir_id } = *self;
268 hir_id.to_stable_hash_key(hcx)
272 impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {
273 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
274 hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
278 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex {
279 type KeyType = DefPathHash;
282 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
283 hcx.local_def_path_hash(*self)
287 impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::lang_items::LangItem {
288 fn hash_stable(&self, _: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
289 ::std::hash::Hash::hash(self, hasher);
293 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
294 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
295 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
296 let hir::TraitCandidate { def_id, import_ids } = self;
298 def_id.hash_stable(hcx, hasher);
299 import_ids.hash_stable(hcx, hasher);
304 impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
305 type KeyType = (DefPathHash, SmallVec<[(DefPathHash, hir::ItemLocalId); 1]>);
307 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType {
308 let hir::TraitCandidate { def_id, import_ids } = self;
310 let import_keys = import_ids
312 .map(|node_id| hcx.node_to_hir_id(*node_id))
313 .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id))
315 (hcx.def_path_hash(*def_id), import_keys)
319 impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
320 fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
321 mem::discriminant(self).hash_stable(hcx, hasher);
325 impl<'hir> HashStable<StableHashingContext<'hir>> for attr::OptimizeAttr {
326 fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
327 mem::discriminant(self).hash_stable(hcx, hasher);