rustc_middle/dep_graph/
dep_node.rs

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        /// This enum serves as an index into arrays built by `make_dep_kind_array`.
37        // This enum has more than u8::MAX variants so we need some kind of multi-byte
38        // encoding. The derived Encodable/Decodable uses leb128 encoding which is
39        // dense when only considering this enum. But DepKind is encoded in a larger
40        // struct, and there we can take advantage of the unused bits in the u16.
41        #[allow(non_camel_case_types)]
42        #[repr(u16)] // Must be kept in sync with the inner type of `DepKind`.
43        enum DepKindDefs {
44            $( $( #[$attr] )* $variant),*
45        }
46
47        #[allow(non_upper_case_globals)]
48        pub mod dep_kinds {
49            use super::*;
50
51            $(
52                // The `as u16` cast must be kept in sync with the inner type of `DepKind`.
53                pub const $variant: DepKind = DepKind::new(DepKindDefs::$variant as u16);
54            )*
55        }
56
57        // This checks that the discriminants of the variants have been assigned consecutively
58        // from 0 so that they can be used as a dense index.
59        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        /// Contains variant => str representations for constructing
79        /// DepNode groups for tests.
80        #[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
89// Create various data structures for each query, and also for a few things
90// that aren't queries.
91rustc_with_all_queries!(define_dep_nodes![
92    /// We use this for most things when incr. comp. is turned off.
93    [] fn Null() -> (),
94    /// We use this to create a forever-red node.
95    [] fn Red() -> (),
96    [] fn SideEffect() -> (),
97    [] fn AnonZeroDeps() -> (),
98    [] fn TraitSelect() -> (),
99    [] fn CompileCodegenUnit() -> (),
100    [] fn CompileMonoItem() -> (),
101]);
102
103// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
104// Be very careful changing this type signature!
105pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
106    DepNode::construct(tcx, dep_kinds::CompileCodegenUnit, &name)
107}
108
109// WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys.
110// Be very careful changing this type signature!
111pub(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    /// Extracts the DefId corresponding to this DepNode. This will work
132    /// if two conditions are met:
133    ///
134    /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
135    /// 2. the item that the DefPath refers to exists in the current tcx.
136    ///
137    /// Condition (1) is determined by the DepKind variant of the
138    /// DepNode. Condition (2) might not be fulfilled if a DepNode
139    /// refers to something from the previous compilation session that
140    /// has been removed.
141    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    /// Used in testing
150    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    /// Used in testing
167    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    // We actually would not need to specialize the implementation of this
285    // method but it's faster to combine the hashes than to instantiate a full
286    // hashing context and stable-hashing state.
287    #[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    // We actually would not need to specialize the implementation of this
312    // method but it's faster to combine the hashes than to instantiate a full
313    // hashing context and stable-hashing state.
314    #[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            // `owner` is local, so is completely defined by the local hash
320            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}