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    [] fn Metadata() -> (),
102]);
103
104// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
105// Be very careful changing this type signature!
106pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
107    DepNode::construct(tcx, dep_kinds::CompileCodegenUnit, &name)
108}
109
110// WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys.
111// Be very careful changing this type signature!
112pub(crate) fn make_compile_mono_item<'tcx>(
113    tcx: TyCtxt<'tcx>,
114    mono_item: &MonoItem<'tcx>,
115) -> DepNode {
116    DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item)
117}
118
119// WARNING: `construct` is generic and does not know that `Metadata` takes `()`s as keys.
120// Be very careful changing this type signature!
121pub(crate) fn make_metadata(tcx: TyCtxt<'_>) -> DepNode {
122    DepNode::construct(tcx, dep_kinds::Metadata, &())
123}
124
125pub trait DepNodeExt: Sized {
126    fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
127
128    fn from_label_string(
129        tcx: TyCtxt<'_>,
130        label: &str,
131        def_path_hash: DefPathHash,
132    ) -> Result<Self, ()>;
133
134    fn has_label_string(label: &str) -> bool;
135}
136
137impl DepNodeExt for DepNode {
138    /// Extracts the DefId corresponding to this DepNode. This will work
139    /// if two conditions are met:
140    ///
141    /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
142    /// 2. the item that the DefPath refers to exists in the current tcx.
143    ///
144    /// Condition (1) is determined by the DepKind variant of the
145    /// DepNode. Condition (2) might not be fulfilled if a DepNode
146    /// refers to something from the previous compilation session that
147    /// has been removed.
148    fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
149        if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
150            tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))
151        } else {
152            None
153        }
154    }
155
156    /// Used in testing
157    fn from_label_string(
158        tcx: TyCtxt<'_>,
159        label: &str,
160        def_path_hash: DefPathHash,
161    ) -> Result<DepNode, ()> {
162        let kind = dep_kind_from_label_string(label)?;
163
164        match tcx.fingerprint_style(kind) {
165            FingerprintStyle::Opaque | FingerprintStyle::HirId => Err(()),
166            FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)),
167            FingerprintStyle::DefPathHash => {
168                Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind))
169            }
170        }
171    }
172
173    /// Used in testing
174    fn has_label_string(label: &str) -> bool {
175        dep_kind_from_label_string(label).is_ok()
176    }
177}
178
179impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
180    #[inline(always)]
181    fn fingerprint_style() -> FingerprintStyle {
182        FingerprintStyle::Unit
183    }
184
185    #[inline(always)]
186    fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
187        Fingerprint::ZERO
188    }
189
190    #[inline(always)]
191    fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
192        Some(())
193    }
194}
195
196impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
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        tcx.def_path_hash(*self).0
205    }
206
207    #[inline(always)]
208    fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
209        tcx.def_path_str(*self)
210    }
211
212    #[inline(always)]
213    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
214        dep_node.extract_def_id(tcx)
215    }
216}
217
218impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
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| id.expect_local())
237    }
238}
239
240impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for OwnerId {
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        self.to_def_id().to_fingerprint(tcx)
249    }
250
251    #[inline(always)]
252    fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
253        self.to_def_id().to_debug_str(tcx)
254    }
255
256    #[inline(always)]
257    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
258        dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
259    }
260}
261
262impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
263    #[inline(always)]
264    fn fingerprint_style() -> FingerprintStyle {
265        FingerprintStyle::DefPathHash
266    }
267
268    #[inline(always)]
269    fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
270        let def_id = self.as_def_id();
271        def_id.to_fingerprint(tcx)
272    }
273
274    #[inline(always)]
275    fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
276        tcx.crate_name(*self).to_string()
277    }
278
279    #[inline(always)]
280    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
281        dep_node.extract_def_id(tcx).map(|id| id.krate)
282    }
283}
284
285impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
286    #[inline(always)]
287    fn fingerprint_style() -> FingerprintStyle {
288        FingerprintStyle::Opaque
289    }
290
291    // We actually would not need to specialize the implementation of this
292    // method but it's faster to combine the hashes than to instantiate a full
293    // hashing context and stable-hashing state.
294    #[inline(always)]
295    fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
296        let (def_id_0, def_id_1) = *self;
297
298        let def_path_hash_0 = tcx.def_path_hash(def_id_0);
299        let def_path_hash_1 = tcx.def_path_hash(def_id_1);
300
301        def_path_hash_0.0.combine(def_path_hash_1.0)
302    }
303
304    #[inline(always)]
305    fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
306        let (def_id_0, def_id_1) = *self;
307
308        format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1))
309    }
310}
311
312impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
313    #[inline(always)]
314    fn fingerprint_style() -> FingerprintStyle {
315        FingerprintStyle::HirId
316    }
317
318    // We actually would not need to specialize the implementation of this
319    // method but it's faster to combine the hashes than to instantiate a full
320    // hashing context and stable-hashing state.
321    #[inline(always)]
322    fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
323        let HirId { owner, local_id } = *self;
324        let def_path_hash = tcx.def_path_hash(owner.to_def_id());
325        Fingerprint::new(
326            // `owner` is local, so is completely defined by the local hash
327            def_path_hash.local_hash(),
328            local_id.as_u32() as u64,
329        )
330    }
331
332    #[inline(always)]
333    fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
334        let HirId { owner, local_id } = *self;
335        format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32())
336    }
337
338    #[inline(always)]
339    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
340        if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
341            let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
342            let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
343            let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
344            let local_id = local_id
345                .as_u64()
346                .try_into()
347                .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}"));
348            Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
349        } else {
350            None
351        }
352    }
353}
354
355impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for ModDefId {
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        DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked)
374    }
375}
376
377impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalModDefId {
378    #[inline(always)]
379    fn fingerprint_style() -> FingerprintStyle {
380        FingerprintStyle::DefPathHash
381    }
382
383    #[inline(always)]
384    fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
385        self.to_def_id().to_fingerprint(tcx)
386    }
387
388    #[inline(always)]
389    fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
390        self.to_def_id().to_debug_str(tcx)
391    }
392
393    #[inline(always)]
394    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
395        LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked)
396    }
397}