1#![allow(internal_features)]
5#![allow(unused_parens)]
6#![cfg_attr(doc, recursion_limit = "256")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
8#![doc(rust_logo)]
9#![feature(min_specialization)]
10#![feature(rustc_attrs)]
11#![feature(rustdoc_internals)]
12use rustc_data_structures::stable_hasher::HashStable;
15use rustc_data_structures::sync::AtomicU64;
16use rustc_middle::arena::Arena;
17use rustc_middle::dep_graph::{self, DepKind, DepKindStruct, DepNodeIndex};
18use rustc_middle::query::erase::{Erase, erase, restore};
19use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
20use rustc_middle::query::plumbing::{DynamicQuery, QuerySystem, QuerySystemFns};
21use rustc_middle::query::{
22 AsLocalKey, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
23 queries,
24};
25use rustc_middle::ty::TyCtxt;
26use rustc_query_system::dep_graph::SerializedDepNodeIndex;
27use rustc_query_system::ich::StableHashingContext;
28use rustc_query_system::query::{
29 CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryStackDeferred,
30 QueryState, get_query_incr, get_query_non_incr,
31};
32use rustc_query_system::{HandleCycleError, Value};
33use rustc_span::{ErrorGuaranteed, Span};
34
35use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
36use crate::profiling_support::QueryKeyStringCache;
37
38#[macro_use]
39mod plumbing;
40pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all};
41
42mod profiling_support;
43pub use self::profiling_support::alloc_self_profile_query_strings;
44
45struct DynamicConfig<
46 'tcx,
47 C: QueryCache,
48 const ANON: bool,
49 const DEPTH_LIMIT: bool,
50 const FEEDABLE: bool,
51> {
52 dynamic: &'tcx DynamicQuery<'tcx, C>,
53}
54
55impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy
56 for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
57{
58}
59impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone
60 for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
61{
62 fn clone(&self) -> Self {
63 DynamicConfig { dynamic: self.dynamic }
64 }
65}
66
67impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
68 QueryConfig<QueryCtxt<'tcx>> for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
69where
70 for<'a> C::Key: HashStable<StableHashingContext<'a>>,
71{
72 type Key = C::Key;
73 type Value = C::Value;
74 type Cache = C;
75
76 #[inline(always)]
77 fn name(self) -> &'static str {
78 self.dynamic.name
79 }
80
81 #[inline(always)]
82 fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
83 (self.dynamic.cache_on_disk)(tcx, key)
84 }
85
86 #[inline(always)]
87 fn query_state<'a>(
88 self,
89 qcx: QueryCtxt<'tcx>,
90 ) -> &'a QueryState<Self::Key, QueryStackDeferred<'tcx>>
91 where
92 QueryCtxt<'tcx>: 'a,
93 {
94 unsafe {
97 &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>)
98 .byte_add(self.dynamic.query_state)
99 .cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>()
100 }
101 }
102
103 #[inline(always)]
104 fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
105 where
106 'tcx: 'a,
107 {
108 unsafe {
111 &*(&qcx.tcx.query_system.caches as *const QueryCaches<'tcx>)
112 .byte_add(self.dynamic.query_cache)
113 .cast::<Self::Cache>()
114 }
115 }
116
117 #[inline(always)]
118 fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
119 (self.dynamic.execute_query)(tcx, key)
120 }
121
122 #[inline(always)]
123 fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
124 (self.dynamic.compute)(qcx.tcx, key)
125 }
126
127 #[inline(always)]
128 fn try_load_from_disk(
129 self,
130 qcx: QueryCtxt<'tcx>,
131 key: &Self::Key,
132 prev_index: SerializedDepNodeIndex,
133 index: DepNodeIndex,
134 ) -> Option<Self::Value> {
135 if self.dynamic.can_load_from_disk {
136 (self.dynamic.try_load_from_disk)(qcx.tcx, key, prev_index, index)
137 } else {
138 None
139 }
140 }
141
142 #[inline]
143 fn loadable_from_disk(
144 self,
145 qcx: QueryCtxt<'tcx>,
146 key: &Self::Key,
147 index: SerializedDepNodeIndex,
148 ) -> bool {
149 (self.dynamic.loadable_from_disk)(qcx.tcx, key, index)
150 }
151
152 fn value_from_cycle_error(
153 self,
154 tcx: TyCtxt<'tcx>,
155 cycle_error: &CycleError,
156 guar: ErrorGuaranteed,
157 ) -> Self::Value {
158 (self.dynamic.value_from_cycle_error)(tcx, cycle_error, guar)
159 }
160
161 #[inline(always)]
162 fn format_value(self) -> fn(&Self::Value) -> String {
163 self.dynamic.format_value
164 }
165
166 #[inline(always)]
167 fn anon(self) -> bool {
168 ANON
169 }
170
171 #[inline(always)]
172 fn eval_always(self) -> bool {
173 self.dynamic.eval_always
174 }
175
176 #[inline(always)]
177 fn depth_limit(self) -> bool {
178 DEPTH_LIMIT
179 }
180
181 #[inline(always)]
182 fn feedable(self) -> bool {
183 FEEDABLE
184 }
185
186 #[inline(always)]
187 fn dep_kind(self) -> DepKind {
188 self.dynamic.dep_kind
189 }
190
191 #[inline(always)]
192 fn handle_cycle_error(self) -> HandleCycleError {
193 self.dynamic.handle_cycle_error
194 }
195
196 #[inline(always)]
197 fn hash_result(self) -> HashResult<Self::Value> {
198 self.dynamic.hash_result
199 }
200}
201
202trait QueryConfigRestored<'tcx> {
205 type RestoredValue;
206 type Config: QueryConfig<QueryCtxt<'tcx>>;
207
208 const NAME: &'static &'static str;
209
210 fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
211 fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
212 -> Self::RestoredValue;
213}
214
215pub fn query_system<'a>(
216 local_providers: Providers,
217 extern_providers: ExternProviders,
218 on_disk_cache: Option<OnDiskCache>,
219 incremental: bool,
220) -> QuerySystem<'a> {
221 QuerySystem {
222 states: Default::default(),
223 arenas: Default::default(),
224 caches: Default::default(),
225 dynamic_queries: dynamic_queries(),
226 on_disk_cache,
227 fns: QuerySystemFns {
228 engine: engine(incremental),
229 local_providers,
230 extern_providers,
231 encode_query_results: encode_all_query_results,
232 try_mark_green,
233 },
234 jobs: AtomicU64::new(1),
235 }
236}
237
238rustc_middle::rustc_query_append! { define_queries! }
239
240pub fn provide(providers: &mut rustc_middle::util::Providers) {
241 providers.hooks.alloc_self_profile_query_strings = alloc_self_profile_query_strings;
242 providers.hooks.query_key_hash_verify_all = query_key_hash_verify_all;
243}