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