• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! The implementation of the query system itself. This defines the macros that
2 //! generate the actual methods on tcx which find and execute the provider,
3 //! manage the caches, and so forth.
4 
5 use crate::rustc_middle::dep_graph::DepContext;
6 use crate::rustc_middle::ty::TyEncoder;
7 use crate::QueryConfigRestored;
8 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
9 use rustc_data_structures::sync::Lock;
10 use rustc_errors::Diagnostic;
11 use rustc_index::Idx;
12 use rustc_middle::dep_graph::{
13     self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
14 };
15 use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
16 use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
17 use rustc_middle::query::Key;
18 use rustc_middle::ty::tls::{self, ImplicitCtxt};
19 use rustc_middle::ty::{self, print::with_no_queries, TyCtxt};
20 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
21 use rustc_query_system::ich::StableHashingContext;
22 use rustc_query_system::query::{
23     force_query, QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects,
24     QueryStackFrame,
25 };
26 use rustc_query_system::{LayoutOfDepth, QueryOverflow};
27 use rustc_serialize::Decodable;
28 use rustc_serialize::Encodable;
29 use rustc_session::Limit;
30 use rustc_span::def_id::LOCAL_CRATE;
31 use std::num::NonZeroU64;
32 use thin_vec::ThinVec;
33 
34 #[derive(Copy, Clone)]
35 pub struct QueryCtxt<'tcx> {
36     pub tcx: TyCtxt<'tcx>,
37 }
38 
39 impl<'tcx> QueryCtxt<'tcx> {
40     #[inline]
new(tcx: TyCtxt<'tcx>) -> Self41     pub fn new(tcx: TyCtxt<'tcx>) -> Self {
42         QueryCtxt { tcx }
43     }
44 }
45 
46 impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
47     type Target = TyCtxt<'tcx>;
48 
49     #[inline]
deref(&self) -> &Self::Target50     fn deref(&self) -> &Self::Target {
51         &self.tcx
52     }
53 }
54 
55 impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
56     type DepKind = rustc_middle::dep_graph::DepKind;
57     type DepContext = TyCtxt<'tcx>;
58 
59     #[inline]
dep_context(&self) -> &Self::DepContext60     fn dep_context(&self) -> &Self::DepContext {
61         &self.tcx
62     }
63 }
64 
65 impl QueryContext for QueryCtxt<'_> {
66     #[inline]
next_job_id(self) -> QueryJobId67     fn next_job_id(self) -> QueryJobId {
68         QueryJobId(
69             NonZeroU64::new(
70                 self.query_system.jobs.fetch_add(1, rustc_data_structures::sync::Ordering::Relaxed),
71             )
72             .unwrap(),
73         )
74     }
75 
76     #[inline]
current_query_job(self) -> Option<QueryJobId>77     fn current_query_job(self) -> Option<QueryJobId> {
78         tls::with_related_context(self.tcx, |icx| icx.query)
79     }
80 
try_collect_active_jobs(self) -> Option<QueryMap<DepKind>>81     fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
82         let mut jobs = QueryMap::default();
83 
84         for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
85             collect(self.tcx, &mut jobs);
86         }
87 
88         Some(jobs)
89     }
90 
91     // Interactions with on_disk_cache
load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects92     fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
93         self.query_system
94             .on_disk_cache
95             .as_ref()
96             .map(|c| c.load_side_effects(self.tcx, prev_dep_node_index))
97             .unwrap_or_default()
98     }
99 
100     #[inline(never)]
101     #[cold]
store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects)102     fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
103         if let Some(c) = self.query_system.on_disk_cache.as_ref() {
104             c.store_side_effects(dep_node_index, side_effects)
105         }
106     }
107 
108     #[inline(never)]
109     #[cold]
store_side_effects_for_anon_node( self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects, )110     fn store_side_effects_for_anon_node(
111         self,
112         dep_node_index: DepNodeIndex,
113         side_effects: QuerySideEffects,
114     ) {
115         if let Some(c) = self.query_system.on_disk_cache.as_ref() {
116             c.store_side_effects_for_anon_node(dep_node_index, side_effects)
117         }
118     }
119 
120     /// Executes a job by changing the `ImplicitCtxt` to point to the
121     /// new query job while it executes. It returns the diagnostics
122     /// captured during execution and the actual result.
123     #[inline(always)]
start_query<R>( self, token: QueryJobId, depth_limit: bool, diagnostics: Option<&Lock<ThinVec<Diagnostic>>>, compute: impl FnOnce() -> R, ) -> R124     fn start_query<R>(
125         self,
126         token: QueryJobId,
127         depth_limit: bool,
128         diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
129         compute: impl FnOnce() -> R,
130     ) -> R {
131         // The `TyCtxt` stored in TLS has the same global interner lifetime
132         // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
133         // when accessing the `ImplicitCtxt`.
134         tls::with_related_context(self.tcx, move |current_icx| {
135             if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
136                 self.depth_limit_error(token);
137             }
138 
139             // Update the `ImplicitCtxt` to point to our new query job.
140             let new_icx = ImplicitCtxt {
141                 tcx: self.tcx,
142                 query: Some(token),
143                 diagnostics,
144                 query_depth: current_icx.query_depth + depth_limit as usize,
145                 task_deps: current_icx.task_deps,
146             };
147 
148             // Use the `ImplicitCtxt` while we execute the query.
149             tls::enter_context(&new_icx, compute)
150         })
151     }
152 
depth_limit_error(self, job: QueryJobId)153     fn depth_limit_error(self, job: QueryJobId) {
154         let mut span = None;
155         let mut layout_of_depth = None;
156         if let Some(map) = self.try_collect_active_jobs() {
157             if let Some((info, depth)) = job.try_find_layout_root(map) {
158                 span = Some(info.job.span);
159                 layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth });
160             }
161         }
162 
163         let suggested_limit = match self.recursion_limit() {
164             Limit(0) => Limit(2),
165             limit => limit * 2,
166         };
167 
168         self.sess.emit_fatal(QueryOverflow {
169             span,
170             layout_of_depth,
171             suggested_limit,
172             crate_name: self.crate_name(LOCAL_CRATE),
173         });
174     }
175 }
176 
try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool177 pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
178     tcx.dep_graph.try_mark_green(QueryCtxt::new(tcx), dep_node).is_some()
179 }
180 
encode_all_query_results<'tcx>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, )181 pub(super) fn encode_all_query_results<'tcx>(
182     tcx: TyCtxt<'tcx>,
183     encoder: &mut CacheEncoder<'_, 'tcx>,
184     query_result_index: &mut EncodedDepNodeIndex,
185 ) {
186     for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) {
187         encode(tcx, encoder, query_result_index);
188     }
189 }
190 
191 macro_rules! handle_cycle_error {
192     ([]) => {{
193         rustc_query_system::HandleCycleError::Error
194     }};
195     ([(fatal_cycle) $($rest:tt)*]) => {{
196         rustc_query_system::HandleCycleError::Fatal
197     }};
198     ([(cycle_delay_bug) $($rest:tt)*]) => {{
199         rustc_query_system::HandleCycleError::DelayBug
200     }};
201     ([$other:tt $($modifiers:tt)*]) => {
202         handle_cycle_error!([$($modifiers)*])
203     };
204 }
205 
206 macro_rules! is_anon {
207     ([]) => {{
208         false
209     }};
210     ([(anon) $($rest:tt)*]) => {{
211         true
212     }};
213     ([$other:tt $($modifiers:tt)*]) => {
214         is_anon!([$($modifiers)*])
215     };
216 }
217 
218 macro_rules! is_eval_always {
219     ([]) => {{
220         false
221     }};
222     ([(eval_always) $($rest:tt)*]) => {{
223         true
224     }};
225     ([$other:tt $($modifiers:tt)*]) => {
226         is_eval_always!([$($modifiers)*])
227     };
228 }
229 
230 macro_rules! depth_limit {
231     ([]) => {{
232         false
233     }};
234     ([(depth_limit) $($rest:tt)*]) => {{
235         true
236     }};
237     ([$other:tt $($modifiers:tt)*]) => {
238         depth_limit!([$($modifiers)*])
239     };
240 }
241 
242 macro_rules! feedable {
243     ([]) => {{
244         false
245     }};
246     ([(feedable) $($rest:tt)*]) => {{
247         true
248     }};
249     ([$other:tt $($modifiers:tt)*]) => {
250         feedable!([$($modifiers)*])
251     };
252 }
253 
254 macro_rules! hash_result {
255     ([][$V:ty]) => {{
256         Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result)))
257     }};
258     ([(no_hash) $($rest:tt)*][$V:ty]) => {{
259         None
260     }};
261     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
262         hash_result!([$($modifiers)*][$($args)*])
263     };
264 }
265 
266 macro_rules! call_provider {
267     ([][$tcx:expr, $name:ident, $key:expr]) => {{
268         ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
269     }};
270     ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
271         if let Some(key) = $key.as_local_key() {
272             ($tcx.query_system.fns.local_providers.$name)($tcx, key)
273         } else {
274             ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
275         }
276     }};
277     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
278         call_provider!([$($modifiers)*][$($args)*])
279     };
280 }
281 
282 macro_rules! should_ever_cache_on_disk {
283     ([]$yes:tt $no:tt) => {{
284         $no
285     }};
286     ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{
287         $yes
288     }};
289     ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => {
290         should_ever_cache_on_disk!([$($modifiers)*]$yes $no)
291     };
292 }
293 
create_query_frame< 'tcx, K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>, >( tcx: TyCtxt<'tcx>, do_describe: fn(TyCtxt<'tcx>, K) -> String, key: K, kind: DepKind, name: &'static str, ) -> QueryStackFrame<DepKind>294 pub(crate) fn create_query_frame<
295     'tcx,
296     K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
297 >(
298     tcx: TyCtxt<'tcx>,
299     do_describe: fn(TyCtxt<'tcx>, K) -> String,
300     key: K,
301     kind: DepKind,
302     name: &'static str,
303 ) -> QueryStackFrame<DepKind> {
304     // Avoid calling queries while formatting the description
305     let description = ty::print::with_no_queries!(
306         // Disable visible paths printing for performance reasons.
307         // Showing visible path instead of any path is not that important in production.
308         ty::print::with_no_visible_paths!(
309             // Force filename-line mode to avoid invoking `type_of` query.
310             ty::print::with_forced_impl_filename_line!(do_describe(tcx, key))
311         )
312     );
313     let description =
314         if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description };
315     let span = if kind == dep_graph::DepKind::def_span || with_no_queries() {
316         // The `def_span` query is used to calculate `default_span`,
317         // so exit to avoid infinite recursion.
318         None
319     } else {
320         Some(key.default_span(tcx))
321     };
322     let def_id = key.key_as_def_id();
323     let def_kind = if kind == dep_graph::DepKind::opt_def_kind || with_no_queries() {
324         // Try to avoid infinite recursion.
325         None
326     } else {
327         def_id.and_then(|def_id| def_id.as_local()).and_then(|def_id| tcx.opt_def_kind(def_id))
328     };
329     let hash = || {
330         tcx.with_stable_hashing_context(|mut hcx| {
331             let mut hasher = StableHasher::new();
332             std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
333             key.hash_stable(&mut hcx, &mut hasher);
334             hasher.finish::<Hash64>()
335         })
336     };
337     let ty_adt_id = key.ty_adt_id();
338 
339     QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash)
340 }
341 
encode_query_results<'a, 'tcx, Q>( query: Q::Config, qcx: QueryCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ) where Q: super::QueryConfigRestored<'tcx>, Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,342 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
343     query: Q::Config,
344     qcx: QueryCtxt<'tcx>,
345     encoder: &mut CacheEncoder<'a, 'tcx>,
346     query_result_index: &mut EncodedDepNodeIndex,
347 ) where
348     Q: super::QueryConfigRestored<'tcx>,
349     Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,
350 {
351     let _timer =
352         qcx.profiler().verbose_generic_activity_with_arg("encode_query_results_for", query.name());
353 
354     assert!(query.query_state(qcx).all_inactive());
355     let cache = query.query_cache(qcx);
356     cache.iter(&mut |key, value, dep_node| {
357         if query.cache_on_disk(qcx.tcx, &key) {
358             let dep_node = SerializedDepNodeIndex::new(dep_node.index());
359 
360             // Record position of the cache entry.
361             query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
362 
363             // Encode the type check tables with the `SerializedDepNodeIndex`
364             // as tag.
365             encoder.encode_tagged(dep_node, &Q::restore(*value));
366         }
367     });
368 }
369 
try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where Q: QueryConfig<QueryCtxt<'tcx>>,370 fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
371 where
372     Q: QueryConfig<QueryCtxt<'tcx>>,
373 {
374     debug_assert!(tcx.dep_graph.is_green(&dep_node));
375 
376     let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
377         panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
378     });
379     if query.cache_on_disk(tcx, &key) {
380         let _ = query.execute_query(tcx, key);
381     }
382 }
383 
loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool384 pub(crate) fn loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
385     if let Some(cache) = tcx.query_system.on_disk_cache.as_ref() {
386         cache.loadable_from_disk(id)
387     } else {
388         false
389     }
390 }
391 
try_load_from_disk<'tcx, V>( tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option<V> where V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,392 pub(crate) fn try_load_from_disk<'tcx, V>(
393     tcx: TyCtxt<'tcx>,
394     prev_index: SerializedDepNodeIndex,
395     index: DepNodeIndex,
396 ) -> Option<V>
397 where
398     V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
399 {
400     let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
401 
402     let prof_timer = tcx.prof.incr_cache_loading();
403 
404     // The call to `with_query_deserialization` enforces that no new `DepNodes`
405     // are created during deserialization. See the docs of that method for more
406     // details.
407     let value = tcx
408         .dep_graph
409         .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
410 
411     prof_timer.finish_with_query_invocation_id(index.into());
412 
413     value
414 }
415 
force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where Q: QueryConfig<QueryCtxt<'tcx>>,416 fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
417 where
418     Q: QueryConfig<QueryCtxt<'tcx>>,
419 {
420     // We must avoid ever having to call `force_from_dep_node()` for a
421     // `DepNode::codegen_unit`:
422     // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
423     // would always end up having to evaluate the first caller of the
424     // `codegen_unit` query that *is* reconstructible. This might very well be
425     // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
426     // to re-trigger calling the `codegen_unit` query with the right key. At
427     // that point we would already have re-done all the work we are trying to
428     // avoid doing in the first place.
429     // The solution is simple: Just explicitly call the `codegen_unit` query for
430     // each CGU, right after partitioning. This way `try_mark_green` will always
431     // hit the cache instead of having to go through `force_from_dep_node`.
432     // This assertion makes sure, we actually keep applying the solution above.
433     debug_assert!(
434         dep_node.kind != DepKind::codegen_unit,
435         "calling force_from_dep_node() on DepKind::codegen_unit"
436     );
437 
438     if let Some(key) = Q::Key::recover(tcx, &dep_node) {
439         #[cfg(debug_assertions)]
440         let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
441         force_query(query, QueryCtxt::new(tcx), key, dep_node);
442         true
443     } else {
444         false
445     }
446 }
447 
query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx> where Q: QueryConfigRestored<'tcx>,448 pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
449 where
450     Q: QueryConfigRestored<'tcx>,
451 {
452     let fingerprint_style = <Q::Config as QueryConfig<QueryCtxt<'tcx>>>::Key::fingerprint_style();
453 
454     if is_anon || !fingerprint_style.reconstructible() {
455         return DepKindStruct {
456             is_anon,
457             is_eval_always,
458             fingerprint_style,
459             force_from_dep_node: None,
460             try_load_from_on_disk_cache: None,
461         };
462     }
463 
464     DepKindStruct {
465         is_anon,
466         is_eval_always,
467         fingerprint_style,
468         force_from_dep_node: Some(|tcx, dep_node| {
469             force_from_dep_node(Q::config(tcx), tcx, dep_node)
470         }),
471         try_load_from_on_disk_cache: Some(|tcx, dep_node| {
472             try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node)
473         }),
474     }
475 }
476 
477 macro_rules! item_if_cached {
478     ([] $tokens:tt) => {};
479     ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
480         $($tokens)*
481     };
482     ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
483         item_if_cached! { [$($modifiers)*] $tokens }
484     };
485 }
486 
487 macro_rules! expand_if_cached {
488     ([], $tokens:expr) => {{
489         None
490     }};
491     ([(cache) $($rest:tt)*], $tokens:expr) => {{
492         Some($tokens)
493     }};
494     ([$other:tt $($modifiers:tt)*], $tokens:expr) => {
495         expand_if_cached!([$($modifiers)*], $tokens)
496     };
497 }
498 
499 /// Don't show the backtrace for query system by default
500 /// use `RUST_BACKTRACE=full` to show all the backtraces
501 #[inline(never)]
__rust_begin_short_backtrace<F, T>(f: F) -> T where F: FnOnce() -> T,502 pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
503 where
504     F: FnOnce() -> T,
505 {
506     let result = f();
507     std::hint::black_box(());
508     result
509 }
510 
511 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
512 // invoked by `rustc_query_append`.
513 macro_rules! define_queries {
514     (
515      $($(#[$attr:meta])*
516         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
517 
518         pub(crate) mod query_impl { $(pub mod $name {
519             use super::super::*;
520             use std::marker::PhantomData;
521 
522             pub mod get_query_incr {
523                 use super::*;
524 
525                 // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
526                 // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
527                 #[inline(never)]
528                 pub fn __rust_end_short_backtrace<'tcx>(
529                     tcx: TyCtxt<'tcx>,
530                     span: Span,
531                     key: queries::$name::Key<'tcx>,
532                     mode: QueryMode,
533                 ) -> Option<Erase<queries::$name::Value<'tcx>>> {
534                     #[cfg(debug_assertions)]
535                     let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
536                     get_query_incr(
537                         QueryType::config(tcx),
538                         QueryCtxt::new(tcx),
539                         span,
540                         key,
541                         mode
542                     )
543                 }
544             }
545 
546             pub mod get_query_non_incr {
547                 use super::*;
548 
549                 #[inline(never)]
550                 pub fn __rust_end_short_backtrace<'tcx>(
551                     tcx: TyCtxt<'tcx>,
552                     span: Span,
553                     key: queries::$name::Key<'tcx>,
554                     __mode: QueryMode,
555                 ) -> Option<Erase<queries::$name::Value<'tcx>>> {
556                     Some(get_query_non_incr(
557                         QueryType::config(tcx),
558                         QueryCtxt::new(tcx),
559                         span,
560                         key,
561                     ))
562                 }
563             }
564 
565             pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> {
566                 DynamicQuery {
567                     name: stringify!($name),
568                     eval_always: is_eval_always!([$($modifiers)*]),
569                     dep_kind: dep_graph::DepKind::$name,
570                     handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
571                     query_state: offset_of!(QueryStates<'tcx> => $name),
572                     query_cache: offset_of!(QueryCaches<'tcx> => $name),
573                     cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
574                     execute_query: |tcx, key| erase(tcx.$name(key)),
575                     compute: |tcx, key| {
576                         #[cfg(debug_assertions)]
577                         let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
578                         __rust_begin_short_backtrace(||
579                             queries::$name::provided_to_erased(
580                                 tcx,
581                                 {
582                                     let ret = call_provider!([$($modifiers)*][tcx, $name, key]);
583                                     tracing::trace!(?ret);
584                                     ret
585                                 }
586                             )
587                         )
588                     },
589                     can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
590                     try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
591                         |tcx, key, prev_index, index| {
592                             if ::rustc_middle::query::cached::$name(tcx, key) {
593                                 let value = $crate::plumbing::try_load_from_disk::<
594                                     queries::$name::ProvidedValue<'tcx>
595                                 >(
596                                     tcx,
597                                     prev_index,
598                                     index,
599                                 );
600                                 value.map(|value| queries::$name::provided_to_erased(tcx, value))
601                             } else {
602                                 None
603                             }
604                         }
605                     } {
606                         |_tcx, _key, _prev_index, _index| None
607                     }),
608                     value_from_cycle_error: |tcx, cycle| {
609                         let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle);
610                         erase(result)
611                     },
612                     loadable_from_disk: |_tcx, _key, _index| {
613                         should_ever_cache_on_disk!([$($modifiers)*] {
614                             ::rustc_middle::query::cached::$name(_tcx, _key) &&
615                                 $crate::plumbing::loadable_from_disk(_tcx, _index)
616                         } {
617                             false
618                         })
619                     },
620                     hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
621                     format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
622                 }
623             }
624 
625             #[derive(Copy, Clone, Default)]
626             pub struct QueryType<'tcx> {
627                 data: PhantomData<&'tcx ()>
628             }
629 
630             impl<'tcx> QueryConfigRestored<'tcx> for QueryType<'tcx> {
631                 type RestoredValue = queries::$name::Value<'tcx>;
632                 type Config = DynamicConfig<
633                     'tcx,
634                     queries::$name::Storage<'tcx>,
635                     { is_anon!([$($modifiers)*]) },
636                     { depth_limit!([$($modifiers)*]) },
637                     { feedable!([$($modifiers)*]) },
638                 >;
639 
640                 #[inline(always)]
641                 fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
642                     DynamicConfig {
643                         dynamic: &tcx.query_system.dynamic_queries.$name,
644                     }
645                 }
646 
647                 #[inline(always)]
648                 fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
649                     restore::<queries::$name::Value<'tcx>>(value)
650                 }
651             }
652 
653             pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap<DepKind>) {
654                 let make_query = |tcx, key| {
655                     let kind = rustc_middle::dep_graph::DepKind::$name;
656                     let name = stringify!($name);
657                     $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
658                 };
659                 tcx.query_system.states.$name.try_collect_active_jobs(
660                     tcx,
661                     make_query,
662                     qmap,
663                 ).unwrap();
664             }
665 
666             pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) {
667                 $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
668                     tcx,
669                     stringify!($name),
670                     &tcx.query_system.caches.$name,
671                     string_cache,
672                 )
673             }
674 
675             item_if_cached! { [$($modifiers)*] {
676                 pub fn encode_query_results<'tcx>(
677                     tcx: TyCtxt<'tcx>,
678                     encoder: &mut CacheEncoder<'_, 'tcx>,
679                     query_result_index: &mut EncodedDepNodeIndex
680                 ) {
681                     $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
682                         query_impl::$name::QueryType::config(tcx),
683                         QueryCtxt::new(tcx),
684                         encoder,
685                         query_result_index,
686                     )
687                 }
688             }}
689         })*}
690 
691         pub(crate) fn engine(incremental: bool) -> QueryEngine {
692             if incremental {
693                 QueryEngine {
694                     $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
695                 }
696             } else {
697                 QueryEngine {
698                     $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
699                 }
700             }
701         }
702 
703         pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
704             DynamicQueries {
705                 $(
706                     $name: query_impl::$name::dynamic_query(),
707                 )*
708             }
709         }
710 
711         // These arrays are used for iteration and can't be indexed by `DepKind`.
712 
713         const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>)] =
714             &[$(query_impl::$name::try_collect_active_jobs),*];
715 
716         const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
717             for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
718         ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
719 
720         const ENCODE_QUERY_RESULTS: &[
721             Option<for<'tcx> fn(
722                 TyCtxt<'tcx>,
723                 &mut CacheEncoder<'_, 'tcx>,
724                 &mut EncodedDepNodeIndex)
725             >
726         ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
727 
728         #[allow(nonstandard_style)]
729         mod query_callbacks {
730             use super::*;
731             use rustc_query_system::dep_graph::FingerprintStyle;
732 
733             // We use this for most things when incr. comp. is turned off.
734             pub fn Null<'tcx>() -> DepKindStruct<'tcx> {
735                 DepKindStruct {
736                     is_anon: false,
737                     is_eval_always: false,
738                     fingerprint_style: FingerprintStyle::Unit,
739                     force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
740                     try_load_from_on_disk_cache: None,
741                 }
742             }
743 
744             // We use this for the forever-red node.
745             pub fn Red<'tcx>() -> DepKindStruct<'tcx> {
746                 DepKindStruct {
747                     is_anon: false,
748                     is_eval_always: false,
749                     fingerprint_style: FingerprintStyle::Unit,
750                     force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
751                     try_load_from_on_disk_cache: None,
752                 }
753             }
754 
755             pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
756                 DepKindStruct {
757                     is_anon: true,
758                     is_eval_always: false,
759                     fingerprint_style: FingerprintStyle::Unit,
760                     force_from_dep_node: None,
761                     try_load_from_on_disk_cache: None,
762                 }
763             }
764 
765             pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
766                 DepKindStruct {
767                     is_anon: false,
768                     is_eval_always: false,
769                     fingerprint_style: FingerprintStyle::Opaque,
770                     force_from_dep_node: None,
771                     try_load_from_on_disk_cache: None,
772                 }
773             }
774 
775             pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
776                 DepKindStruct {
777                     is_anon: false,
778                     is_eval_always: false,
779                     fingerprint_style: FingerprintStyle::Opaque,
780                     force_from_dep_node: None,
781                     try_load_from_on_disk_cache: None,
782                 }
783             }
784 
785             $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
786                 $crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
787                     is_anon!([$($modifiers)*]),
788                     is_eval_always!([$($modifiers)*]),
789                 )
790             })*
791         }
792 
793         pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
794             arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
795         }
796     }
797 }
798