//! 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, StableHasherResult}; use std::mem; use syntax::ast; use syntax::attr; impl<'a> HashStable> 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> for DefId { type KeyType = DefPathHash; #[inline] fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { hcx.def_path_hash(*self) } } impl<'a> HashStable> 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> 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> 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> 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> 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 NodeIds 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> 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> 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> 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_stable_hash_for!(struct ast::Label { ident }); impl<'a> HashStable> 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 node, ref span, } = *self; node.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); }) } } impl_stable_hash_for_spanned!(hir::FieldPat); impl_stable_hash_for_spanned!(hir::BinOpKind); impl_stable_hash_for!(struct hir::Stmt { hir_id, node, span, }); impl_stable_hash_for_spanned!(ast::Name); impl<'a> HashStable> 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 node, ref attrs } = *self; span.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); }) } } impl_stable_hash_for_spanned!(usize); impl_stable_hash_for_spanned!(ast::Ident); impl_stable_hash_for!(struct ast::Ident { name, span, }); impl<'a> HashStable> 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 node, span } = *self; hcx.hash_hir_item_like(|hcx| { ident.name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); generics.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); }); } } impl<'a> HashStable> 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 node, 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); node.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); }); } } impl_stable_hash_for!(enum ::syntax::ast::CrateSugar { JustCrate, PubCrate, }); impl<'a> HashStable> 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_stable_hash_for_spanned!(hir::VisibilityKind); impl<'a> HashStable> 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 DefPathHashes 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_stable_hash_for_spanned!(hir::VariantKind); impl<'a> HashStable> for hir::Item { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Item { ident, ref attrs, hir_id: _, ref node, ref vis, span } = *self; hcx.hash_hir_item_like(|hcx| { ident.name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); }); } } impl<'a> HashStable> for hir::Body { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { ref arguments, ref value, is_generator, } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { arguments.hash_stable(hcx, hasher); value.hash_stable(hcx, hasher); is_generator.hash_stable(hcx, hasher); }); } } impl<'a> ToStableHashKey> 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> 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> 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> 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> 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_id, } = *self; def_id.hash_stable(hcx, hasher); import_id.hash_stable(hcx, hasher); }); } } impl<'a> ToStableHashKey> for hir::TraitCandidate { type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>); fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType { let hir::TraitCandidate { def_id, import_id, } = *self; let import_id = import_id.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)); (hcx.def_path_hash(def_id), import_id) } } impl<'hir> HashStable> for attr::InlineAttr { fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); } } impl<'hir> HashStable> for attr::OptimizeAttr { fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); } }