]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/dep_graph/dep_node.rs
Auto merge of #86118 - spastorino:tait-soundness-bug, r=nikomatsakis
[rust.git] / compiler / rustc_middle / src / dep_graph / dep_node.rs
1 //! Nodes in the dependency graph.
2 //!
3 //! A node in the [dependency graph] is represented by a [`DepNode`].
4 //! A `DepNode` consists of a [`DepKind`] (which
5 //! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.)
6 //! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which
7 //! depends on the node's `DepKind`. Together, the kind and the fingerprint
8 //! fully identify a dependency node, even across multiple compilation sessions.
9 //! In other words, the value of the fingerprint does not depend on anything
10 //! that is specific to a given compilation session, like an unpredictable
11 //! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a
12 //! pointer. The concept behind this could be compared to how git commit hashes
13 //! uniquely identify a given commit. The fingerprinting approach has
14 //! a few advantages:
15 //!
16 //! * A `DepNode` can simply be serialized to disk and loaded in another session
17 //!   without the need to do any "rebasing" (like we have to do for Spans and
18 //!   NodeIds) or "retracing" (like we had to do for `DefId` in earlier
19 //!   implementations of the dependency graph).
20 //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to
21 //!   implement `Copy`, `Sync`, `Send`, `Freeze`, etc.
22 //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into
23 //!   memory without any post-processing (e.g., "abomination-style" pointer
24 //!   reconstruction).
25 //! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that
26 //!   refer to things that do not exist anymore. In previous implementations
27 //!   `DepNode` contained a `DefId`. A `DepNode` referring to something that
28 //!   had been removed between the previous and the current compilation session
29 //!   could not be instantiated because the current compilation session
30 //!   contained no `DefId` for thing that had been removed.
31 //!
32 //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro
33 //! defines the `DepKind` enum. Each `DepKind` has its own parameters that are
34 //! needed at runtime in order to construct a valid `DepNode` fingerprint.
35 //! However, only `CompileCodegenUnit` and `CompileMonoItem` are constructed
36 //! explicitly (with `make_compile_codegen_unit` cq `make_compile_mono_item`).
37 //!
38 //! Because the macro sees what parameters a given `DepKind` requires, it can
39 //! "infer" some properties for each kind of `DepNode`:
40 //!
41 //! * Whether a `DepNode` of a given kind has any parameters at all. Some
42 //!   `DepNode`s could represent global concepts with only one value.
43 //! * Whether it is possible, in principle, to reconstruct a query key from a
44 //!   given `DepNode`. Many `DepKind`s only require a single `DefId` parameter,
45 //!   in which case it is possible to map the node's fingerprint back to the
46 //!   `DefId` it was computed from. In other cases, too much information gets
47 //!   lost during fingerprint computation.
48 //!
49 //! `make_compile_codegen_unit` and `make_compile_mono_items`, together with
50 //! `DepNode::new()`, ensures that only valid `DepNode` instances can be
51 //! constructed. For example, the API does not allow for constructing
52 //! parameterless `DepNode`s with anything other than a zeroed out fingerprint.
53 //! More generally speaking, it relieves the user of the `DepNode` API of
54 //! having to know how to compute the expected fingerprint for a given set of
55 //! node parameters.
56 //!
57 //! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html
58
59 use crate::mir::mono::MonoItem;
60 use crate::ty::TyCtxt;
61
62 use rustc_data_structures::fingerprint::Fingerprint;
63 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
64 use rustc_hir::definitions::DefPathHash;
65 use rustc_hir::HirId;
66 use rustc_span::symbol::Symbol;
67 use std::hash::Hash;
68
69 pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
70
71 /// This struct stores metadata about each DepKind.
72 ///
73 /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
74 /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
75 /// jump table instead of large matches.
76 pub struct DepKindStruct {
77     /// Whether the DepNode has parameters (query keys).
78     pub(super) has_params: bool,
79
80     /// Anonymous queries cannot be replayed from one compiler invocation to the next.
81     /// When their result is needed, it is recomputed. They are useful for fine-grained
82     /// dependency tracking, and caching within one compiler invocation.
83     pub(super) is_anon: bool,
84
85     /// Eval-always queries do not track their dependencies, and are always recomputed, even if
86     /// their inputs have not changed since the last compiler invocation. The result is still
87     /// cached within one compiler invocation.
88     pub(super) is_eval_always: bool,
89
90     /// Whether the query key can be recovered from the hashed fingerprint.
91     /// See [DepNodeParams] trait for the behaviour of each key type.
92     // FIXME: Make this a simple boolean once DepNodeParams::can_reconstruct_query_key
93     // can be made a specialized associated const.
94     can_reconstruct_query_key: fn() -> bool,
95 }
96
97 impl std::ops::Deref for DepKind {
98     type Target = DepKindStruct;
99     fn deref(&self) -> &DepKindStruct {
100         &DEP_KINDS[*self as usize]
101     }
102 }
103
104 impl DepKind {
105     #[inline(always)]
106     pub fn can_reconstruct_query_key(&self) -> bool {
107         // Only fetch the DepKindStruct once.
108         let data: &DepKindStruct = &**self;
109         if data.is_anon {
110             return false;
111         }
112
113         (data.can_reconstruct_query_key)()
114     }
115 }
116
117 // erase!() just makes tokens go away. It's used to specify which macro argument
118 // is repeated (i.e., which sub-expression of the macro we are in) but don't need
119 // to actually use any of the arguments.
120 macro_rules! erase {
121     ($x:tt) => {{}};
122 }
123
124 macro_rules! is_anon_attr {
125     (anon) => {
126         true
127     };
128     ($attr:ident) => {
129         false
130     };
131 }
132
133 macro_rules! is_eval_always_attr {
134     (eval_always) => {
135         true
136     };
137     ($attr:ident) => {
138         false
139     };
140 }
141
142 macro_rules! contains_anon_attr {
143     ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_anon_attr!($attr) | )* false});
144 }
145
146 macro_rules! contains_eval_always_attr {
147     ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false});
148 }
149
150 #[allow(non_upper_case_globals)]
151 pub mod dep_kind {
152     use super::*;
153     use crate::ty::query::query_keys;
154
155     // We use this for most things when incr. comp. is turned off.
156     pub const Null: DepKindStruct = DepKindStruct {
157         has_params: false,
158         is_anon: false,
159         is_eval_always: false,
160
161         can_reconstruct_query_key: || true,
162     };
163
164     pub const TraitSelect: DepKindStruct = DepKindStruct {
165         has_params: false,
166         is_anon: true,
167         is_eval_always: false,
168
169         can_reconstruct_query_key: || true,
170     };
171
172     pub const CompileCodegenUnit: DepKindStruct = DepKindStruct {
173         has_params: true,
174         is_anon: false,
175         is_eval_always: false,
176
177         can_reconstruct_query_key: || false,
178     };
179
180     pub const CompileMonoItem: DepKindStruct = DepKindStruct {
181         has_params: true,
182         is_anon: false,
183         is_eval_always: false,
184
185         can_reconstruct_query_key: || false,
186     };
187
188     macro_rules! define_query_dep_kinds {
189         ($(
190             [$($attrs:tt)*]
191             $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
192         ,)*) => (
193             $(pub const $variant: DepKindStruct = {
194                 const has_params: bool = $({ erase!($tuple_arg_ty); true } |)* false;
195                 const is_anon: bool = contains_anon_attr!($($attrs)*);
196                 const is_eval_always: bool = contains_eval_always_attr!($($attrs)*);
197
198                 #[inline(always)]
199                 fn can_reconstruct_query_key() -> bool {
200                     <query_keys::$variant<'_> as DepNodeParams<TyCtxt<'_>>>
201                         ::can_reconstruct_query_key()
202                 }
203
204                 DepKindStruct {
205                     has_params,
206                     is_anon,
207                     is_eval_always,
208                     can_reconstruct_query_key,
209                 }
210             };)*
211         );
212     }
213
214     rustc_dep_node_append!([define_query_dep_kinds!][]);
215 }
216
217 macro_rules! define_dep_nodes {
218     (<$tcx:tt>
219     $(
220         [$($attrs:tt)*]
221         $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
222       ,)*
223     ) => (
224         #[macro_export]
225         macro_rules! make_dep_kind_array {
226             ($mod:ident) => {[ $(($mod::$variant),)* ]};
227         }
228
229         static DEP_KINDS: &[DepKindStruct] = &make_dep_kind_array!(dep_kind);
230
231         /// This enum serves as an index into the `DEP_KINDS` array.
232         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
233         #[allow(non_camel_case_types)]
234         pub enum DepKind {
235             $($variant),*
236         }
237
238         fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
239             match label {
240                 $(stringify!($variant) => Ok(DepKind::$variant),)*
241                 _ => Err(()),
242             }
243         }
244
245         /// Contains variant => str representations for constructing
246         /// DepNode groups for tests.
247         #[allow(dead_code, non_upper_case_globals)]
248         pub mod label_strs {
249            $(
250                 pub const $variant: &str = stringify!($variant);
251             )*
252         }
253     );
254 }
255
256 rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
257     // We use this for most things when incr. comp. is turned off.
258     [] Null,
259
260     [anon] TraitSelect,
261
262     // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below.
263     [] CompileCodegenUnit(Symbol),
264
265     // WARNING: if `MonoItem` is changed, make sure you update `make_compile_mono_item` below.
266     // Only used by rustc_codegen_cranelift
267     [] CompileMonoItem(MonoItem),
268 ]);
269
270 // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
271 // Be very careful changing this type signature!
272 crate fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
273     DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name)
274 }
275
276 // WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys.
277 // Be very careful changing this type signature!
278 crate fn make_compile_mono_item(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode {
279     DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item)
280 }
281
282 pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
283
284 // We keep a lot of `DepNode`s in memory during compilation. It's not
285 // required that their size stay the same, but we don't want to change
286 // it inadvertently. This assert just ensures we're aware of any change.
287 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
288 static_assert_size!(DepNode, 18);
289
290 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
291 static_assert_size!(DepNode, 24);
292
293 pub trait DepNodeExt: Sized {
294     /// Construct a DepNode from the given DepKind and DefPathHash. This
295     /// method will assert that the given DepKind actually requires a
296     /// single DefId/DefPathHash parameter.
297     fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
298
299     /// Extracts the DefId corresponding to this DepNode. This will work
300     /// if two conditions are met:
301     ///
302     /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
303     /// 2. the item that the DefPath refers to exists in the current tcx.
304     ///
305     /// Condition (1) is determined by the DepKind variant of the
306     /// DepNode. Condition (2) might not be fulfilled if a DepNode
307     /// refers to something from the previous compilation session that
308     /// has been removed.
309     fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
310
311     /// Used in testing
312     fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<Self, ()>;
313
314     /// Used in testing
315     fn has_label_string(label: &str) -> bool;
316 }
317
318 impl DepNodeExt for DepNode {
319     /// Construct a DepNode from the given DepKind and DefPathHash. This
320     /// method will assert that the given DepKind actually requires a
321     /// single DefId/DefPathHash parameter.
322     fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
323         debug_assert!(kind.can_reconstruct_query_key() && kind.has_params);
324         DepNode { kind, hash: def_path_hash.0.into() }
325     }
326
327     /// Extracts the DefId corresponding to this DepNode. This will work
328     /// if two conditions are met:
329     ///
330     /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
331     /// 2. the item that the DefPath refers to exists in the current tcx.
332     ///
333     /// Condition (1) is determined by the DepKind variant of the
334     /// DepNode. Condition (2) might not be fulfilled if a DepNode
335     /// refers to something from the previous compilation session that
336     /// has been removed.
337     fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
338         if self.kind.can_reconstruct_query_key() {
339             tcx.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
340         } else {
341             None
342         }
343     }
344
345     /// Used in testing
346     fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
347         let kind = dep_kind_from_label_string(label)?;
348
349         if !kind.can_reconstruct_query_key() {
350             return Err(());
351         }
352
353         if kind.has_params {
354             Ok(DepNode::from_def_path_hash(def_path_hash, kind))
355         } else {
356             Ok(DepNode::new_no_params(kind))
357         }
358     }
359
360     /// Used in testing
361     fn has_label_string(label: &str) -> bool {
362         dep_kind_from_label_string(label).is_ok()
363     }
364 }
365
366 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
367     #[inline(always)]
368     fn can_reconstruct_query_key() -> bool {
369         true
370     }
371
372     fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
373         Fingerprint::ZERO
374     }
375
376     fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
377         Some(())
378     }
379 }
380
381 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
382     #[inline(always)]
383     fn can_reconstruct_query_key() -> bool {
384         true
385     }
386
387     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
388         let hash = tcx.def_path_hash(*self);
389         // If this is a foreign `DefId`, store its current value
390         // in the incremental cache. When we decode the cache,
391         // we will use the old DefIndex as an initial guess for
392         // a lookup into the crate metadata.
393         if !self.is_local() {
394             if let Some(cache) = &tcx.on_disk_cache {
395                 cache.store_foreign_def_id_hash(*self, hash);
396             }
397         }
398         hash.0
399     }
400
401     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
402         tcx.def_path_str(*self)
403     }
404
405     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
406         dep_node.extract_def_id(tcx)
407     }
408 }
409
410 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
411     #[inline(always)]
412     fn can_reconstruct_query_key() -> bool {
413         true
414     }
415
416     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
417         self.to_def_id().to_fingerprint(tcx)
418     }
419
420     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
421         self.to_def_id().to_debug_str(tcx)
422     }
423
424     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
425         dep_node.extract_def_id(tcx).map(|id| id.expect_local())
426     }
427 }
428
429 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
430     #[inline(always)]
431     fn can_reconstruct_query_key() -> bool {
432         true
433     }
434
435     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
436         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
437         def_id.to_fingerprint(tcx)
438     }
439
440     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
441         tcx.crate_name(*self).to_string()
442     }
443
444     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
445         dep_node.extract_def_id(tcx).map(|id| id.krate)
446     }
447 }
448
449 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
450     #[inline(always)]
451     fn can_reconstruct_query_key() -> bool {
452         false
453     }
454
455     // We actually would not need to specialize the implementation of this
456     // method but it's faster to combine the hashes than to instantiate a full
457     // hashing context and stable-hashing state.
458     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
459         let (def_id_0, def_id_1) = *self;
460
461         let def_path_hash_0 = tcx.def_path_hash(def_id_0);
462         let def_path_hash_1 = tcx.def_path_hash(def_id_1);
463
464         def_path_hash_0.0.combine(def_path_hash_1.0)
465     }
466
467     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
468         let (def_id_0, def_id_1) = *self;
469
470         format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1))
471     }
472 }
473
474 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
475     #[inline(always)]
476     fn can_reconstruct_query_key() -> bool {
477         false
478     }
479
480     // We actually would not need to specialize the implementation of this
481     // method but it's faster to combine the hashes than to instantiate a full
482     // hashing context and stable-hashing state.
483     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
484         let HirId { owner, local_id } = *self;
485
486         let def_path_hash = tcx.def_path_hash(owner.to_def_id());
487         let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into());
488
489         def_path_hash.0.combine(local_id)
490     }
491 }