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