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