rustc_hir/
stable_hash_impls.rs

1use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
2use rustc_span::def_id::DefPathHash;
3
4use crate::HashIgnoredAttrId;
5use crate::hir::{
6    AttributeMap, BodyId, Crate, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId,
7};
8use crate::hir_id::{HirId, ItemLocalId};
9
10/// Requirements for a `StableHashingContext` to be used in this crate.
11/// This is a hack to allow using the `HashStable_Generic` derive macro
12/// instead of implementing everything in `rustc_middle`.
13pub trait HashStableContext:
14    rustc_attr_data_structures::HashStableContext
15    + rustc_ast::HashStableContext
16    + rustc_abi::HashStableContext
17{
18    fn hash_attr_id(&mut self, id: &HashIgnoredAttrId, hasher: &mut StableHasher);
19}
20
21impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
22    type KeyType = (DefPathHash, ItemLocalId);
23
24    #[inline]
25    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
26        let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx);
27        (def_path_hash, self.local_id)
28    }
29}
30
31impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemLocalId {
32    type KeyType = ItemLocalId;
33
34    #[inline]
35    fn to_stable_hash_key(&self, _: &HirCtx) -> ItemLocalId {
36        *self
37    }
38}
39
40impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for BodyId {
41    type KeyType = (DefPathHash, ItemLocalId);
42
43    #[inline]
44    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
45        let BodyId { hir_id } = *self;
46        hir_id.to_stable_hash_key(hcx)
47    }
48}
49
50impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId {
51    type KeyType = DefPathHash;
52
53    #[inline]
54    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
55        self.owner_id.def_id.to_stable_hash_key(hcx)
56    }
57}
58
59impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
60    type KeyType = DefPathHash;
61
62    #[inline]
63    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
64        self.owner_id.def_id.to_stable_hash_key(hcx)
65    }
66}
67
68impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
69    type KeyType = DefPathHash;
70
71    #[inline]
72    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
73        self.owner_id.def_id.to_stable_hash_key(hcx)
74    }
75}
76
77impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId {
78    type KeyType = DefPathHash;
79
80    #[inline]
81    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
82        self.owner_id.def_id.to_stable_hash_key(hcx)
83    }
84}
85
86// The following implementations of HashStable for `ItemId`, `TraitItemId`, and
87// `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
88// the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
89// are used when another item in the HIR is *referenced* and we certainly
90// want to pick up on a reference changing its target, so we hash the NodeIds
91// in "DefPath Mode".
92
93impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'tcx> {
94    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
95        // We ignore the `nodes` and `bodies` fields since these refer to information included in
96        // `hash` which is hashed in the collector and used for the crate hash.
97        // `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
98        // the body satisfies the condition of two nodes being different have different
99        // `hash_stable` results.
100        let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self;
101        opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher);
102    }
103}
104
105impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap<'tcx> {
106    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
107        // We ignore the `map` since it refers to information included in `opt_hash` which is
108        // hashed in the collector and used for the crate hash.
109        let AttributeMap { opt_hash, define_opaque: _, map: _ } = *self;
110        opt_hash.unwrap().hash_stable(hcx, hasher);
111    }
112}
113
114impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate<'_> {
115    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
116        let Crate { owners: _, opt_hir_hash } = self;
117        opt_hir_hash.unwrap().hash_stable(hcx, hasher)
118    }
119}
120
121impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HashIgnoredAttrId {
122    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
123        hcx.hash_attr_id(self, hasher)
124    }
125}