| //! This module contains `HashStable` implementations for various HIR data |
| //! types in no particular order. |
| |
| use crate::hir; |
| use crate::hir::map::DefPathHash; |
| use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX}; |
| use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint}; |
| |
| use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher}; |
| use smallvec::SmallVec; |
| use std::mem; |
| use syntax::attr; |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for DefId { |
| #[inline] |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.def_path_hash(*self).hash_stable(hcx, hasher); |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId { |
| type KeyType = DefPathHash; |
| |
| #[inline] |
| fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { |
| hcx.def_path_hash(*self) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId { |
| #[inline] |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher); |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId { |
| type KeyType = DefPathHash; |
| |
| #[inline] |
| fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { |
| hcx.def_path_hash(self.to_def_id()) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for CrateNum { |
| #[inline] |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.def_path_hash(DefId { |
| krate: *self, |
| index: CRATE_DEF_INDEX |
| }).hash_stable(hcx, hasher); |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum { |
| type KeyType = DefPathHash; |
| |
| #[inline] |
| fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { |
| let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX }; |
| def_id.to_stable_hash_key(hcx) |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> |
| for hir::ItemLocalId { |
| type KeyType = hir::ItemLocalId; |
| |
| #[inline] |
| fn to_stable_hash_key(&self, |
| _: &StableHashingContext<'a>) |
| -> hir::ItemLocalId { |
| *self |
| } |
| } |
| |
| // The following implementations of HashStable for `ItemId`, `TraitItemId`, and |
| // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within |
| // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al |
| // are used when another item in the HIR is *referenced* and we certainly |
| // want to pick up on a reference changing its target, so we hash the NodeIds |
| // in "DefPath Mode". |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::ItemId { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::ItemId { |
| id |
| } = *self; |
| |
| hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { |
| id.hash_stable(hcx, hasher); |
| }) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItemId { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::TraitItemId { |
| hir_id |
| } = * self; |
| |
| hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { |
| hir_id.hash_stable(hcx, hasher); |
| }) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::ImplItemId { |
| hir_id |
| } = * self; |
| |
| hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { |
| hir_id.hash_stable(hcx, hasher); |
| }) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.while_hashing_hir_bodies(true, |hcx| { |
| let hir::Ty { |
| hir_id: _, |
| ref kind, |
| ref span, |
| } = *self; |
| |
| kind.hash_stable(hcx, hasher); |
| span.hash_stable(hcx, hasher); |
| }) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.while_hashing_hir_bodies(true, |hcx| { |
| let hir::Expr { |
| hir_id: _, |
| ref span, |
| ref kind, |
| ref attrs |
| } = *self; |
| |
| span.hash_stable(hcx, hasher); |
| kind.hash_stable(hcx, hasher); |
| attrs.hash_stable(hcx, hasher); |
| }) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::TraitItem { |
| hir_id: _, |
| ident, |
| ref attrs, |
| ref generics, |
| ref kind, |
| span |
| } = *self; |
| |
| hcx.hash_hir_item_like(|hcx| { |
| ident.name.hash_stable(hcx, hasher); |
| attrs.hash_stable(hcx, hasher); |
| generics.hash_stable(hcx, hasher); |
| kind.hash_stable(hcx, hasher); |
| span.hash_stable(hcx, hasher); |
| }); |
| } |
| } |
| |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::ImplItem { |
| hir_id: _, |
| ident, |
| ref vis, |
| defaultness, |
| ref attrs, |
| ref generics, |
| ref kind, |
| span |
| } = *self; |
| |
| hcx.hash_hir_item_like(|hcx| { |
| ident.name.hash_stable(hcx, hasher); |
| vis.hash_stable(hcx, hasher); |
| defaultness.hash_stable(hcx, hasher); |
| attrs.hash_stable(hcx, hasher); |
| generics.hash_stable(hcx, hasher); |
| kind.hash_stable(hcx, hasher); |
| span.hash_stable(hcx, hasher); |
| }); |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| mem::discriminant(self).hash_stable(hcx, hasher); |
| match *self { |
| hir::VisibilityKind::Public | |
| hir::VisibilityKind::Inherited => { |
| // No fields to hash. |
| } |
| hir::VisibilityKind::Crate(sugar) => { |
| sugar.hash_stable(hcx, hasher); |
| } |
| hir::VisibilityKind::Restricted { ref path, hir_id } => { |
| hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { |
| hir_id.hash_stable(hcx, hasher); |
| }); |
| path.hash_stable(hcx, hasher); |
| } |
| } |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::Mod { |
| inner: ref inner_span, |
| ref item_ids, |
| } = *self; |
| |
| inner_span.hash_stable(hcx, hasher); |
| |
| // Combining the `DefPathHash`s directly is faster than feeding them |
| // into the hasher. Because we use a commutative combine, we also don't |
| // have to sort the array. |
| let item_ids_hash = item_ids |
| .iter() |
| .map(|id| { |
| let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx); |
| debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0)); |
| def_path_hash.0 |
| }).fold(Fingerprint::ZERO, |a, b| { |
| a.combine_commutative(b) |
| }); |
| |
| item_ids.len().hash_stable(hcx, hasher); |
| item_ids_hash.hash_stable(hcx, hasher); |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::Item { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::Item { |
| ident, |
| ref attrs, |
| hir_id: _, |
| ref kind, |
| ref vis, |
| span |
| } = *self; |
| |
| hcx.hash_hir_item_like(|hcx| { |
| ident.name.hash_stable(hcx, hasher); |
| attrs.hash_stable(hcx, hasher); |
| kind.hash_stable(hcx, hasher); |
| vis.hash_stable(hcx, hasher); |
| span.hash_stable(hcx, hasher); |
| }); |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::Body { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| let hir::Body { |
| params, |
| value, |
| generator_kind, |
| } = self; |
| |
| hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { |
| params.hash_stable(hcx, hasher); |
| value.hash_stable(hcx, hasher); |
| generator_kind.hash_stable(hcx, hasher); |
| }); |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId { |
| type KeyType = (DefPathHash, hir::ItemLocalId); |
| |
| #[inline] |
| fn to_stable_hash_key(&self, |
| hcx: &StableHashingContext<'a>) |
| -> (DefPathHash, hir::ItemLocalId) { |
| let hir::BodyId { hir_id } = *self; |
| hir_id.to_stable_hash_key(hcx) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex { |
| |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.local_def_path_hash(*self).hash_stable(hcx, hasher); |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex { |
| type KeyType = DefPathHash; |
| |
| #[inline] |
| fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { |
| hcx.local_def_path_hash(*self) |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::lang_items::LangItem { |
| fn hash_stable(&self, _: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| ::std::hash::Hash::hash(self, hasher); |
| } |
| } |
| |
| impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
| hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { |
| let hir::TraitCandidate { |
| def_id, |
| import_ids, |
| } = self; |
| |
| def_id.hash_stable(hcx, hasher); |
| import_ids.hash_stable(hcx, hasher); |
| }); |
| } |
| } |
| |
| impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate { |
| type KeyType = (DefPathHash, SmallVec<[(DefPathHash, hir::ItemLocalId); 1]>); |
| |
| fn to_stable_hash_key(&self, |
| hcx: &StableHashingContext<'a>) |
| -> Self::KeyType { |
| let hir::TraitCandidate { |
| def_id, |
| import_ids, |
| } = self; |
| |
| let import_keys = import_ids.iter().map(|node_id| hcx.node_to_hir_id(*node_id)) |
| .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), |
| hir_id.local_id)).collect(); |
| (hcx.def_path_hash(*def_id), import_keys) |
| } |
| } |
| |
| impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { |
| mem::discriminant(self).hash_stable(hcx, hasher); |
| } |
| } |
| |
| impl<'hir> HashStable<StableHashingContext<'hir>> for attr::OptimizeAttr { |
| fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { |
| mem::discriminant(self).hash_stable(hcx, hasher); |
| } |
| } |