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