1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};

use crate::hir::{
    BodyId, Expr, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId,
    Ty, VisibilityKind,
};
use crate::hir_id::{HirId, ItemLocalId};
use rustc_span::def_id::{DefPathHash, LocalDefId};

/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in librustc_middle.
pub trait HashStableContext:
    rustc_ast::HashStableContext + rustc_target::HashStableContext
{
    fn hash_hir_id(&mut self, _: HirId, hasher: &mut StableHasher);
    fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher);
    fn hash_reference_to_item(&mut self, _: HirId, hasher: &mut StableHasher);
    fn hash_hir_mod(&mut self, _: &Mod<'_>, hasher: &mut StableHasher);
    fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher);
    fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher);
    fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher);
    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F);
    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash;
}

impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
    type KeyType = (DefPathHash, ItemLocalId);

    #[inline]
    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
        let def_path_hash = hcx.local_def_path_hash(self.owner);
        (def_path_hash, self.local_id)
    }
}

impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
    type KeyType = (DefPathHash, ItemLocalId);

    #[inline]
    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
        self.hir_id.to_stable_hash_key(hcx)
    }
}

impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
    type KeyType = (DefPathHash, ItemLocalId);

    #[inline]
    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
        self.hir_id.to_stable_hash_key(hcx)
    }
}

impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId {
    type KeyType = (DefPathHash, ItemLocalId);

    #[inline]
    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
        self.hir_id.to_stable_hash_key(hcx)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_hir_id(*self, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for BodyId {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_body_id(*self, hasher)
    }
}

// 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<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ItemId {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_reference_to_item(self.id, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItemId {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_reference_to_item(self.hir_id, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_reference_to_item(self.hir_id, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItemId {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_reference_to_item(self.hir_id, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Mod<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_hir_mod(self, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Expr<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_hir_expr(self, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Ty<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_hir_ty(self, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for VisibilityKind<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        hcx.hash_hir_visibility_kind(self, hasher)
    }
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        let 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<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        let 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<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
        let 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);
        });
    }
}