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 AnonZeroDeps() -> (),
93 [] fn TraitSelect() -> (),
94 [] fn CompileCodegenUnit() -> (),
95 [] fn CompileMonoItem() -> (),
96]);
97
98pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
101 DepNode::construct(tcx, dep_kinds::CompileCodegenUnit, &name)
102}
103
104pub(crate) fn make_compile_mono_item<'tcx>(
107 tcx: TyCtxt<'tcx>,
108 mono_item: &MonoItem<'tcx>,
109) -> DepNode {
110 DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item)
111}
112
113pub trait DepNodeExt: Sized {
114 fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
115
116 fn from_label_string(
117 tcx: TyCtxt<'_>,
118 label: &str,
119 def_path_hash: DefPathHash,
120 ) -> Result<Self, ()>;
121
122 fn has_label_string(label: &str) -> bool;
123}
124
125impl DepNodeExt for DepNode {
126 fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
137 if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
138 tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))
139 } else {
140 None
141 }
142 }
143
144 fn from_label_string(
146 tcx: TyCtxt<'_>,
147 label: &str,
148 def_path_hash: DefPathHash,
149 ) -> Result<DepNode, ()> {
150 let kind = dep_kind_from_label_string(label)?;
151
152 match tcx.fingerprint_style(kind) {
153 FingerprintStyle::Opaque | FingerprintStyle::HirId => Err(()),
154 FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)),
155 FingerprintStyle::DefPathHash => {
156 Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind))
157 }
158 }
159 }
160
161 fn has_label_string(label: &str) -> bool {
163 dep_kind_from_label_string(label).is_ok()
164 }
165}
166
167impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
168 #[inline(always)]
169 fn fingerprint_style() -> FingerprintStyle {
170 FingerprintStyle::Unit
171 }
172
173 #[inline(always)]
174 fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
175 Fingerprint::ZERO
176 }
177
178 #[inline(always)]
179 fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
180 Some(())
181 }
182}
183
184impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
185 #[inline(always)]
186 fn fingerprint_style() -> FingerprintStyle {
187 FingerprintStyle::DefPathHash
188 }
189
190 #[inline(always)]
191 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
192 tcx.def_path_hash(*self).0
193 }
194
195 #[inline(always)]
196 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
197 tcx.def_path_str(*self)
198 }
199
200 #[inline(always)]
201 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
202 dep_node.extract_def_id(tcx)
203 }
204}
205
206impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
207 #[inline(always)]
208 fn fingerprint_style() -> FingerprintStyle {
209 FingerprintStyle::DefPathHash
210 }
211
212 #[inline(always)]
213 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
214 self.to_def_id().to_fingerprint(tcx)
215 }
216
217 #[inline(always)]
218 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
219 self.to_def_id().to_debug_str(tcx)
220 }
221
222 #[inline(always)]
223 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
224 dep_node.extract_def_id(tcx).map(|id| id.expect_local())
225 }
226}
227
228impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for OwnerId {
229 #[inline(always)]
230 fn fingerprint_style() -> FingerprintStyle {
231 FingerprintStyle::DefPathHash
232 }
233
234 #[inline(always)]
235 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
236 self.to_def_id().to_fingerprint(tcx)
237 }
238
239 #[inline(always)]
240 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
241 self.to_def_id().to_debug_str(tcx)
242 }
243
244 #[inline(always)]
245 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
246 dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
247 }
248}
249
250impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
251 #[inline(always)]
252 fn fingerprint_style() -> FingerprintStyle {
253 FingerprintStyle::DefPathHash
254 }
255
256 #[inline(always)]
257 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
258 let def_id = self.as_def_id();
259 def_id.to_fingerprint(tcx)
260 }
261
262 #[inline(always)]
263 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
264 tcx.crate_name(*self).to_string()
265 }
266
267 #[inline(always)]
268 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
269 dep_node.extract_def_id(tcx).map(|id| id.krate)
270 }
271}
272
273impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
274 #[inline(always)]
275 fn fingerprint_style() -> FingerprintStyle {
276 FingerprintStyle::Opaque
277 }
278
279 #[inline(always)]
283 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
284 let (def_id_0, def_id_1) = *self;
285
286 let def_path_hash_0 = tcx.def_path_hash(def_id_0);
287 let def_path_hash_1 = tcx.def_path_hash(def_id_1);
288
289 def_path_hash_0.0.combine(def_path_hash_1.0)
290 }
291
292 #[inline(always)]
293 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
294 let (def_id_0, def_id_1) = *self;
295
296 format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1))
297 }
298}
299
300impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
301 #[inline(always)]
302 fn fingerprint_style() -> FingerprintStyle {
303 FingerprintStyle::HirId
304 }
305
306 #[inline(always)]
310 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
311 let HirId { owner, local_id } = *self;
312 let def_path_hash = tcx.def_path_hash(owner.to_def_id());
313 Fingerprint::new(
314 def_path_hash.local_hash(),
316 local_id.as_u32() as u64,
317 )
318 }
319
320 #[inline(always)]
321 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
322 let HirId { owner, local_id } = *self;
323 format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32())
324 }
325
326 #[inline(always)]
327 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
328 if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
329 let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
330 let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
331 let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
332 let local_id = local_id
333 .as_u64()
334 .try_into()
335 .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}"));
336 Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
337 } else {
338 None
339 }
340 }
341}
342
343impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for ModDefId {
344 #[inline(always)]
345 fn fingerprint_style() -> FingerprintStyle {
346 FingerprintStyle::DefPathHash
347 }
348
349 #[inline(always)]
350 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
351 self.to_def_id().to_fingerprint(tcx)
352 }
353
354 #[inline(always)]
355 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
356 self.to_def_id().to_debug_str(tcx)
357 }
358
359 #[inline(always)]
360 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
361 DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked)
362 }
363}
364
365impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalModDefId {
366 #[inline(always)]
367 fn fingerprint_style() -> FingerprintStyle {
368 FingerprintStyle::DefPathHash
369 }
370
371 #[inline(always)]
372 fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
373 self.to_def_id().to_fingerprint(tcx)
374 }
375
376 #[inline(always)]
377 fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
378 self.to_def_id().to_debug_str(tcx)
379 }
380
381 #[inline(always)]
382 fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
383 LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked)
384 }
385}