rustc_middle/dep_graph/
dep_node_key.rs1use std::fmt::Debug;
2
3use rustc_data_structures::fingerprint::Fingerprint;
4use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
6use rustc_hir::definitions::DefPathHash;
7use rustc_hir::{HirId, ItemLocalId, OwnerId};
8
9use crate::dep_graph::{DepNode, KeyFingerprintStyle};
10use crate::ich::StableHashingContext;
11use crate::ty::TyCtxt;
12
13pub trait DepNodeKey<'tcx>: Debug + Sized {
15 fn key_fingerprint_style() -> KeyFingerprintStyle;
16
17 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint;
20
21 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
28}
29
30impl<'tcx, T> DepNodeKey<'tcx> for T
32where
33 T: for<'a> HashStable<StableHashingContext<'a>> + Debug,
34{
35 #[inline(always)]
36 default fn key_fingerprint_style() -> KeyFingerprintStyle {
37 KeyFingerprintStyle::Opaque
38 }
39
40 #[inline(always)]
41 default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
42 tcx.with_stable_hashing_context(|mut hcx| {
43 let mut hasher = StableHasher::new();
44 self.hash_stable(&mut hcx, &mut hasher);
45 hasher.finish()
46 })
47 }
48
49 #[inline(always)]
50 default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
51 None
52 }
53}
54
55impl<'tcx> DepNodeKey<'tcx> for () {
56 #[inline(always)]
57 fn key_fingerprint_style() -> KeyFingerprintStyle {
58 KeyFingerprintStyle::Unit
59 }
60
61 #[inline(always)]
62 fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
63 Fingerprint::ZERO
64 }
65
66 #[inline(always)]
67 fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
68 Some(())
69 }
70}
71
72impl<'tcx> DepNodeKey<'tcx> for DefId {
73 #[inline(always)]
74 fn key_fingerprint_style() -> KeyFingerprintStyle {
75 KeyFingerprintStyle::DefPathHash
76 }
77
78 #[inline(always)]
79 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
80 tcx.def_path_hash(*self).0
81 }
82
83 #[inline(always)]
84 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
85 dep_node.extract_def_id(tcx)
86 }
87}
88
89impl<'tcx> DepNodeKey<'tcx> for LocalDefId {
90 #[inline(always)]
91 fn key_fingerprint_style() -> KeyFingerprintStyle {
92 KeyFingerprintStyle::DefPathHash
93 }
94
95 #[inline(always)]
96 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
97 self.to_def_id().to_fingerprint(tcx)
98 }
99
100 #[inline(always)]
101 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
102 dep_node.extract_def_id(tcx).map(|id| id.expect_local())
103 }
104}
105
106impl<'tcx> DepNodeKey<'tcx> for OwnerId {
107 #[inline(always)]
108 fn key_fingerprint_style() -> KeyFingerprintStyle {
109 KeyFingerprintStyle::DefPathHash
110 }
111
112 #[inline(always)]
113 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
114 self.to_def_id().to_fingerprint(tcx)
115 }
116
117 #[inline(always)]
118 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
119 dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
120 }
121}
122
123impl<'tcx> DepNodeKey<'tcx> for CrateNum {
124 #[inline(always)]
125 fn key_fingerprint_style() -> KeyFingerprintStyle {
126 KeyFingerprintStyle::DefPathHash
127 }
128
129 #[inline(always)]
130 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
131 let def_id = self.as_def_id();
132 def_id.to_fingerprint(tcx)
133 }
134
135 #[inline(always)]
136 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
137 dep_node.extract_def_id(tcx).map(|id| id.krate)
138 }
139}
140
141impl<'tcx> DepNodeKey<'tcx> for (DefId, DefId) {
142 #[inline(always)]
143 fn key_fingerprint_style() -> KeyFingerprintStyle {
144 KeyFingerprintStyle::Opaque
145 }
146
147 #[inline(always)]
151 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
152 let (def_id_0, def_id_1) = *self;
153
154 let def_path_hash_0 = tcx.def_path_hash(def_id_0);
155 let def_path_hash_1 = tcx.def_path_hash(def_id_1);
156
157 def_path_hash_0.0.combine(def_path_hash_1.0)
158 }
159}
160
161impl<'tcx> DepNodeKey<'tcx> for HirId {
162 #[inline(always)]
163 fn key_fingerprint_style() -> KeyFingerprintStyle {
164 KeyFingerprintStyle::HirId
165 }
166
167 #[inline(always)]
171 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
172 let HirId { owner, local_id } = *self;
173 let def_path_hash = tcx.def_path_hash(owner.to_def_id());
174 Fingerprint::new(
175 def_path_hash.local_hash(),
177 local_id.as_u32() as u64,
178 )
179 }
180
181 #[inline(always)]
182 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
183 if tcx.key_fingerprint_style(dep_node.kind) == KeyFingerprintStyle::HirId {
184 let (local_hash, local_id) = Fingerprint::from(dep_node.key_fingerprint).split();
185 let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
186 let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
187 let local_id = local_id
188 .as_u64()
189 .try_into()
190 .unwrap_or_else(|_| {
::core::panicking::panic_fmt(format_args!("local id should be u32, found {0:?}",
local_id));
}panic!("local id should be u32, found {local_id:?}"));
191 Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
192 } else {
193 None
194 }
195 }
196}
197
198impl<'tcx> DepNodeKey<'tcx> for ModDefId {
199 #[inline(always)]
200 fn key_fingerprint_style() -> KeyFingerprintStyle {
201 KeyFingerprintStyle::DefPathHash
202 }
203
204 #[inline(always)]
205 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
206 self.to_def_id().to_fingerprint(tcx)
207 }
208
209 #[inline(always)]
210 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
211 DefId::try_recover_key(tcx, dep_node).map(ModDefId::new_unchecked)
212 }
213}
214
215impl<'tcx> DepNodeKey<'tcx> for LocalModDefId {
216 #[inline(always)]
217 fn key_fingerprint_style() -> KeyFingerprintStyle {
218 KeyFingerprintStyle::DefPathHash
219 }
220
221 #[inline(always)]
222 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
223 self.to_def_id().to_fingerprint(tcx)
224 }
225
226 #[inline(always)]
227 fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
228 LocalDefId::try_recover_key(tcx, dep_node).map(LocalModDefId::new_unchecked)
229 }
230}