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