1use rustc_data_structures::fingerprint::Fingerprint;
2use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
3use rustc_hir::definitions::DefPathHash;
4use rustc_hir::{HirId, ItemLocalId, OwnerId};
5pub use rustc_query_system::dep_graph::DepNode;
6use rustc_query_system::dep_graph::FingerprintStyle;
7pub use rustc_query_system::dep_graph::dep_node::DepKind;
8pub(crate) use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
9use rustc_span::Symbol;
10
11use crate::mir::mono::MonoItem;
12use crate::ty::TyCtxt;
13
14macro_rules! define_dep_nodes {
15 (
16 $($(#[$attr:meta])*
17 [$($modifiers:tt)*] fn $variant:ident($($K:tt)*) -> $V:ty,)*) => {
18
19 #[macro_export]
20 macro_rules! make_dep_kind_array {
21 ($mod:ident) => {[ $($mod::$variant()),* ]};
22 }
23
24 #[allow(non_camel_case_types)]
30 #[repr(u16)] enum DepKindDefs {
32 $( $( #[$attr] )* $variant),*
33 }
34
35 #[allow(non_upper_case_globals)]
36 pub mod dep_kinds {
37 use super::*;
38
39 $(
40 pub const $variant: DepKind = DepKind::new(DepKindDefs::$variant as u16);
42 )*
43 }
44
45 pub(crate) const DEP_KIND_VARIANTS: u16 = {
48 let deps = &[$(dep_kinds::$variant,)*];
49 let mut i = 0;
50 while i < deps.len() {
51 if i != deps[i].as_usize() {
52 panic!();
53 }
54 i += 1;
55 }
56 deps.len() as u16
57 };
58
59 pub(super) fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
60 match label {
61 $(stringify!($variant) => Ok(dep_kinds::$variant),)*
62 _ => Err(()),
63 }
64 }
65
66 #[allow(dead_code, non_upper_case_globals)]
69 pub mod label_strs {
70 $(
71 pub const $variant: &str = stringify!($variant);
72 )*
73 }
74 };
75}
76
77rustc_query_append!(define_dep_nodes![
78 [] fn Null() -> (),
80 [] fn Red() -> (),
82 [] fn TraitSelect() -> (),
83 [] fn CompileCodegenUnit() -> (),
84 [] fn CompileMonoItem() -> (),
85]);
86
87pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
90 DepNode::construct(tcx, dep_kinds::CompileCodegenUnit, &name)
91}
92
93pub(crate) fn make_compile_mono_item<'tcx>(
96 tcx: TyCtxt<'tcx>,
97 mono_item: &MonoItem<'tcx>,
98) -> DepNode {
99 DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item)
100}
101
102pub trait DepNodeExt: Sized {
103 fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
104
105 fn from_label_string(
106 tcx: TyCtxt<'_>,
107 label: &str,
108 def_path_hash: DefPathHash,
109 ) -> Result<Self, ()>;
110
111 fn has_label_string(label: &str) -> bool;
112}
113
114impl DepNodeExt for DepNode {
115 fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
126 if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
127 tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))
128 } else {
129 None
130 }
131 }
132
133 fn from_label_string(
135 tcx: TyCtxt<'_>,
136 label: &str,
137 def_path_hash: DefPathHash,
138 ) -> Result<DepNode, ()> {
139 let kind = dep_kind_from_label_string(label)?;
140
141 match tcx.fingerprint_style(kind) {
142 FingerprintStyle::Opaque | FingerprintStyle::HirId => Err(()),
143 FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)),
144 FingerprintStyle::DefPathHash => {
145 Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind))
146 }
147 }
148 }
149
150 fn has_label_string(label: &str) -> bool {
152 dep_kind_from_label_string(label).is_ok()
153 }
154}
155
156impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
157 #[inline(always)]
158 fn fingerprint_style() -> FingerprintStyle {
159 FingerprintStyle::Unit
160 }
161
162 #[inline(always)]
163 fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
164 Fingerprint::ZERO
165 }
166
167 #[inline(always)]
168 fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
169 Some(())
170 }
171}
172
173impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
174 #[inline(always)]
175 fn fingerprint_style() -> FingerprintStyle {
176 FingerprintStyle::DefPathHash
177 }
178
179 #[inline(always)]
180 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
181 tcx.def_path_hash(*self).0
182 }
183
184 #[inline(always)]
185 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
186 tcx.def_path_str(*self)
187 }
188
189 #[inline(always)]
190 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
191 dep_node.extract_def_id(tcx)
192 }
193}
194
195impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
196 #[inline(always)]
197 fn fingerprint_style() -> FingerprintStyle {
198 FingerprintStyle::DefPathHash
199 }
200
201 #[inline(always)]
202 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
203 self.to_def_id().to_fingerprint(tcx)
204 }
205
206 #[inline(always)]
207 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
208 self.to_def_id().to_debug_str(tcx)
209 }
210
211 #[inline(always)]
212 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
213 dep_node.extract_def_id(tcx).map(|id| id.expect_local())
214 }
215}
216
217impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for OwnerId {
218 #[inline(always)]
219 fn fingerprint_style() -> FingerprintStyle {
220 FingerprintStyle::DefPathHash
221 }
222
223 #[inline(always)]
224 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
225 self.to_def_id().to_fingerprint(tcx)
226 }
227
228 #[inline(always)]
229 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
230 self.to_def_id().to_debug_str(tcx)
231 }
232
233 #[inline(always)]
234 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
235 dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
236 }
237}
238
239impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
240 #[inline(always)]
241 fn fingerprint_style() -> FingerprintStyle {
242 FingerprintStyle::DefPathHash
243 }
244
245 #[inline(always)]
246 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
247 let def_id = self.as_def_id();
248 def_id.to_fingerprint(tcx)
249 }
250
251 #[inline(always)]
252 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
253 tcx.crate_name(*self).to_string()
254 }
255
256 #[inline(always)]
257 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
258 dep_node.extract_def_id(tcx).map(|id| id.krate)
259 }
260}
261
262impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
263 #[inline(always)]
264 fn fingerprint_style() -> FingerprintStyle {
265 FingerprintStyle::Opaque
266 }
267
268 #[inline(always)]
272 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
273 let (def_id_0, def_id_1) = *self;
274
275 let def_path_hash_0 = tcx.def_path_hash(def_id_0);
276 let def_path_hash_1 = tcx.def_path_hash(def_id_1);
277
278 def_path_hash_0.0.combine(def_path_hash_1.0)
279 }
280
281 #[inline(always)]
282 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
283 let (def_id_0, def_id_1) = *self;
284
285 format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1))
286 }
287}
288
289impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
290 #[inline(always)]
291 fn fingerprint_style() -> FingerprintStyle {
292 FingerprintStyle::HirId
293 }
294
295 #[inline(always)]
299 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
300 let HirId { owner, local_id } = *self;
301 let def_path_hash = tcx.def_path_hash(owner.to_def_id());
302 Fingerprint::new(
303 def_path_hash.local_hash(),
305 local_id.as_u32() as u64,
306 )
307 }
308
309 #[inline(always)]
310 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
311 let HirId { owner, local_id } = *self;
312 format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32())
313 }
314
315 #[inline(always)]
316 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
317 if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
318 let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
319 let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
320 let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
321 let local_id = local_id
322 .as_u64()
323 .try_into()
324 .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}"));
325 Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
326 } else {
327 None
328 }
329 }
330}
331
332impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for ModDefId {
333 #[inline(always)]
334 fn fingerprint_style() -> FingerprintStyle {
335 FingerprintStyle::DefPathHash
336 }
337
338 #[inline(always)]
339 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
340 self.to_def_id().to_fingerprint(tcx)
341 }
342
343 #[inline(always)]
344 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
345 self.to_def_id().to_debug_str(tcx)
346 }
347
348 #[inline(always)]
349 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
350 DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked)
351 }
352}
353
354impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalModDefId {
355 #[inline(always)]
356 fn fingerprint_style() -> FingerprintStyle {
357 FingerprintStyle::DefPathHash
358 }
359
360 #[inline(always)]
361 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
362 self.to_def_id().to_fingerprint(tcx)
363 }
364
365 #[inline(always)]
366 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
367 self.to_def_id().to_debug_str(tcx)
368 }
369
370 #[inline(always)]
371 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
372 LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked)
373 }
374}