]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_query_system/src/query/mod.rs
Auto merge of #89541 - workingjubilee:abbrev-shufvec-t, r=Mark-Simulacrum
[rust.git] / compiler / rustc_query_system / src / query / mod.rs
1 mod plumbing;
2 pub use self::plumbing::*;
3
4 mod job;
5 #[cfg(parallel_compiler)]
6 pub use self::job::deadlock;
7 pub use self::job::{print_query_stack, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap};
8
9 mod caches;
10 pub use self::caches::{
11     ArenaCacheSelector, CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage,
12 };
13
14 mod config;
15 pub use self::config::{QueryAccessors, QueryConfig, QueryDescription};
16
17 use crate::dep_graph::{DepNode, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
18
19 use rustc_data_structures::sync::Lock;
20 use rustc_data_structures::thin_vec::ThinVec;
21 use rustc_errors::Diagnostic;
22 use rustc_span::Span;
23
24 /// Description of a frame in the query stack.
25 ///
26 /// This is mostly used in case of cycles for error reporting.
27 #[derive(Clone, Debug)]
28 pub struct QueryStackFrame {
29     pub name: &'static str,
30     pub description: String,
31     span: Option<Span>,
32     /// The `DefKind` this query frame is associated with, if applicable.
33     ///
34     /// We can't use `rustc_hir::def::DefKind` because `rustc_hir` is not
35     /// available in `rustc_query_system`. Instead, we have a simplified
36     /// custom version of it, called [`SimpleDefKind`].
37     def_kind: Option<SimpleDefKind>,
38     /// This hash is used to deterministically pick
39     /// a query to remove cycles in the parallel compiler.
40     #[cfg(parallel_compiler)]
41     hash: u64,
42 }
43
44 /// A simplified version of `rustc_hir::def::DefKind`.
45 ///
46 /// It was added to help improve cycle errors caused by recursive type aliases.
47 /// As of August 2021, `rustc_query_system` cannot depend on `rustc_hir`
48 /// because it would create a dependency cycle. So, instead, a simplified
49 /// version of `DefKind` was added to `rustc_query_system`.
50 ///
51 /// `DefKind`s are converted to `SimpleDefKind`s in `rustc_query_impl`.
52 #[derive(Debug, Copy, Clone)]
53 pub enum SimpleDefKind {
54     Struct,
55     Enum,
56     Union,
57     Trait,
58     TyAlias,
59     TraitAlias,
60
61     // FIXME: add more from `rustc_hir::def::DefKind` and then remove `Other`
62     Other,
63 }
64
65 impl QueryStackFrame {
66     #[inline]
67     pub fn new(
68         name: &'static str,
69         description: String,
70         span: Option<Span>,
71         def_kind: Option<SimpleDefKind>,
72         _hash: impl FnOnce() -> u64,
73     ) -> Self {
74         Self {
75             name,
76             description,
77             span,
78             def_kind,
79             #[cfg(parallel_compiler)]
80             hash: _hash(),
81         }
82     }
83
84     // FIXME(eddyb) Get more valid `Span`s on queries.
85     #[inline]
86     pub fn default_span(&self, span: Span) -> Span {
87         if !span.is_dummy() {
88             return span;
89         }
90         self.span.unwrap_or(span)
91     }
92 }
93
94 /// Tracks 'side effects' for a particular query.
95 /// This struct is saved to disk along with the query result,
96 /// and loaded from disk if we mark the query as green.
97 /// This allows us to 'replay' changes to global state
98 /// that would otherwise only occur if we actually
99 /// executed the query method.
100 #[derive(Debug, Clone, Default, Encodable, Decodable)]
101 pub struct QuerySideEffects {
102     /// Stores any diagnostics emitted during query execution.
103     /// These diagnostics will be re-emitted if we mark
104     /// the query as green.
105     pub(super) diagnostics: ThinVec<Diagnostic>,
106 }
107
108 impl QuerySideEffects {
109     pub fn is_empty(&self) -> bool {
110         let QuerySideEffects { diagnostics } = self;
111         diagnostics.is_empty()
112     }
113     pub fn append(&mut self, other: QuerySideEffects) {
114         let QuerySideEffects { diagnostics } = self;
115         diagnostics.extend(other.diagnostics);
116     }
117 }
118
119 pub trait QueryContext: HasDepContext {
120     /// Get the query information from the TLS context.
121     fn current_query_job(&self) -> Option<QueryJobId<Self::DepKind>>;
122
123     fn try_collect_active_jobs(&self) -> Option<QueryMap<Self::DepKind>>;
124
125     /// Load data from the on-disk cache.
126     fn try_load_from_on_disk_cache(&self, dep_node: &DepNode<Self::DepKind>);
127
128     /// Try to force a dep node to execute and see if it's green.
129     fn try_force_from_dep_node(&self, dep_node: &DepNode<Self::DepKind>) -> bool;
130
131     /// Load side effects associated to the node in the previous session.
132     fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
133
134     /// Register diagnostics for the given node, for use in next session.
135     fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects);
136
137     /// Register diagnostics for the given node, for use in next session.
138     fn store_side_effects_for_anon_node(
139         &self,
140         dep_node_index: DepNodeIndex,
141         side_effects: QuerySideEffects,
142     );
143
144     /// Executes a job by changing the `ImplicitCtxt` to point to the
145     /// new query job while it executes. It returns the diagnostics
146     /// captured during execution and the actual result.
147     fn start_query<R>(
148         &self,
149         token: QueryJobId<Self::DepKind>,
150         diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
151         compute: impl FnOnce() -> R,
152     ) -> R;
153 }