rustc_query_impl/
plumbing.rs

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
5use std::num::NonZero;
6
7use rustc_data_structures::jobserver::Proxy;
8use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
9use rustc_data_structures::sync::{DynSend, DynSync};
10use rustc_data_structures::unord::UnordMap;
11use rustc_hashes::Hash64;
12use rustc_hir::limit::Limit;
13use rustc_index::Idx;
14use rustc_middle::bug;
15use rustc_middle::dep_graph::{
16    self, DepContext, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
17    dep_kinds,
18};
19use rustc_middle::query::Key;
20use rustc_middle::query::on_disk_cache::{
21    AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
22};
23use rustc_middle::ty::codec::TyEncoder;
24use rustc_middle::ty::print::with_reduced_queries;
25use rustc_middle::ty::tls::{self, ImplicitCtxt};
26use rustc_middle::ty::{self, TyCtxt};
27use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
28use rustc_query_system::ich::StableHashingContext;
29use rustc_query_system::query::{
30    QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect,
31    QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query,
32};
33use rustc_query_system::{QueryOverflow, QueryOverflowNote};
34use rustc_serialize::{Decodable, Encodable};
35use rustc_span::def_id::LOCAL_CRATE;
36
37use crate::QueryConfigRestored;
38
39#[derive(Copy, Clone)]
40pub struct QueryCtxt<'tcx> {
41    pub tcx: TyCtxt<'tcx>,
42}
43
44impl<'tcx> QueryCtxt<'tcx> {
45    #[inline]
46    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
47        QueryCtxt { tcx }
48    }
49}
50
51impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
52    type Target = TyCtxt<'tcx>;
53
54    #[inline]
55    fn deref(&self) -> &Self::Target {
56        &self.tcx
57    }
58}
59
60impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
61    type Deps = rustc_middle::dep_graph::DepsType;
62    type DepContext = TyCtxt<'tcx>;
63
64    #[inline]
65    fn dep_context(&self) -> &Self::DepContext {
66        &self.tcx
67    }
68}
69
70impl<'tcx> QueryContext for QueryCtxt<'tcx> {
71    type QueryInfo = QueryStackDeferred<'tcx>;
72
73    #[inline]
74    fn jobserver_proxy(&self) -> &Proxy {
75        &*self.jobserver_proxy
76    }
77
78    #[inline]
79    fn next_job_id(self) -> QueryJobId {
80        QueryJobId(
81            NonZero::new(self.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
82                .unwrap(),
83        )
84    }
85
86    #[inline]
87    fn current_query_job(self) -> Option<QueryJobId> {
88        tls::with_related_context(self.tcx, |icx| icx.query)
89    }
90
91    /// Returns a map of currently active query jobs.
92    ///
93    /// If `require_complete` is `true`, this function locks all shards of the
94    /// query results to produce a complete map, which always returns `Ok`.
95    /// Otherwise, it may return an incomplete map as an error if any shard
96    /// lock cannot be acquired.
97    ///
98    /// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
99    /// especially when called from within a deadlock handler, unless a
100    /// complete map is needed and no deadlock is possible at this call site.
101    fn collect_active_jobs(
102        self,
103        require_complete: bool,
104    ) -> Result<QueryMap<QueryStackDeferred<'tcx>>, QueryMap<QueryStackDeferred<'tcx>>> {
105        let mut jobs = QueryMap::default();
106        let mut complete = true;
107
108        for collect in super::COLLECT_ACTIVE_JOBS.iter() {
109            if collect(self.tcx, &mut jobs, require_complete).is_none() {
110                complete = false;
111            }
112        }
113
114        if complete { Ok(jobs) } else { Err(jobs) }
115    }
116
117    fn lift_query_info(
118        self,
119        info: &QueryStackDeferred<'tcx>,
120    ) -> rustc_query_system::query::QueryStackFrameExtra {
121        info.extract()
122    }
123
124    // Interactions with on_disk_cache
125    fn load_side_effect(
126        self,
127        prev_dep_node_index: SerializedDepNodeIndex,
128    ) -> Option<QuerySideEffect> {
129        self.query_system
130            .on_disk_cache
131            .as_ref()
132            .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
133    }
134
135    #[inline(never)]
136    #[cold]
137    fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
138        if let Some(c) = self.query_system.on_disk_cache.as_ref() {
139            c.store_side_effect(dep_node_index, side_effect)
140        }
141    }
142
143    /// Executes a job by changing the `ImplicitCtxt` to point to the
144    /// new query job while it executes.
145    #[inline(always)]
146    fn start_query<R>(
147        self,
148        token: QueryJobId,
149        depth_limit: bool,
150        compute: impl FnOnce() -> R,
151    ) -> R {
152        // The `TyCtxt` stored in TLS has the same global interner lifetime
153        // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
154        // when accessing the `ImplicitCtxt`.
155        tls::with_related_context(self.tcx, move |current_icx| {
156            if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
157                self.depth_limit_error(token);
158            }
159
160            // Update the `ImplicitCtxt` to point to our new query job.
161            let new_icx = ImplicitCtxt {
162                tcx: self.tcx,
163                query: Some(token),
164                query_depth: current_icx.query_depth + depth_limit as usize,
165                task_deps: current_icx.task_deps,
166            };
167
168            // Use the `ImplicitCtxt` while we execute the query.
169            tls::enter_context(&new_icx, compute)
170        })
171    }
172
173    fn depth_limit_error(self, job: QueryJobId) {
174        let query_map = self.collect_active_jobs(true).expect("failed to collect active queries");
175        let (info, depth) = job.find_dep_kind_root(query_map);
176
177        let suggested_limit = match self.recursion_limit() {
178            Limit(0) => Limit(2),
179            limit => limit * 2,
180        };
181
182        self.sess.dcx().emit_fatal(QueryOverflow {
183            span: info.job.span,
184            note: QueryOverflowNote {
185                desc: self.lift_query_info(&info.query.info).description,
186                depth,
187            },
188            suggested_limit,
189            crate_name: self.crate_name(LOCAL_CRATE),
190        });
191    }
192}
193
194pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
195    tcx.dep_graph.try_mark_green(QueryCtxt::new(tcx), dep_node).is_some()
196}
197
198pub(super) fn encode_all_query_results<'tcx>(
199    tcx: TyCtxt<'tcx>,
200    encoder: &mut CacheEncoder<'_, 'tcx>,
201    query_result_index: &mut EncodedDepNodeIndex,
202) {
203    for encode in super::ENCODE_QUERY_RESULTS.iter().copied().flatten() {
204        encode(tcx, encoder, query_result_index);
205    }
206}
207
208pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
209    if tcx.sess().opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) {
210        tcx.sess.time("query_key_hash_verify_all", || {
211            for verify in super::QUERY_KEY_HASH_VERIFY.iter() {
212                verify(tcx);
213            }
214        })
215    }
216}
217
218macro_rules! handle_cycle_error {
219    ([]) => {{
220        rustc_query_system::HandleCycleError::Error
221    }};
222    ([(fatal_cycle) $($rest:tt)*]) => {{
223        rustc_query_system::HandleCycleError::Fatal
224    }};
225    ([(cycle_stash) $($rest:tt)*]) => {{
226        rustc_query_system::HandleCycleError::Stash
227    }};
228    ([(cycle_delay_bug) $($rest:tt)*]) => {{
229        rustc_query_system::HandleCycleError::DelayBug
230    }};
231    ([$other:tt $($modifiers:tt)*]) => {
232        handle_cycle_error!([$($modifiers)*])
233    };
234}
235
236macro_rules! is_anon {
237    ([]) => {{
238        false
239    }};
240    ([(anon) $($rest:tt)*]) => {{
241        true
242    }};
243    ([$other:tt $($modifiers:tt)*]) => {
244        is_anon!([$($modifiers)*])
245    };
246}
247
248macro_rules! is_eval_always {
249    ([]) => {{
250        false
251    }};
252    ([(eval_always) $($rest:tt)*]) => {{
253        true
254    }};
255    ([$other:tt $($modifiers:tt)*]) => {
256        is_eval_always!([$($modifiers)*])
257    };
258}
259
260macro_rules! depth_limit {
261    ([]) => {{
262        false
263    }};
264    ([(depth_limit) $($rest:tt)*]) => {{
265        true
266    }};
267    ([$other:tt $($modifiers:tt)*]) => {
268        depth_limit!([$($modifiers)*])
269    };
270}
271
272macro_rules! feedable {
273    ([]) => {{
274        false
275    }};
276    ([(feedable) $($rest:tt)*]) => {{
277        true
278    }};
279    ([$other:tt $($modifiers:tt)*]) => {
280        feedable!([$($modifiers)*])
281    };
282}
283
284macro_rules! hash_result {
285    ([][$V:ty]) => {{
286        Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result)))
287    }};
288    ([(no_hash) $($rest:tt)*][$V:ty]) => {{
289        None
290    }};
291    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
292        hash_result!([$($modifiers)*][$($args)*])
293    };
294}
295
296macro_rules! call_provider {
297    ([][$tcx:expr, $name:ident, $key:expr]) => {{
298        ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
299    }};
300    ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
301        if let Some(key) = $key.as_local_key() {
302            ($tcx.query_system.fns.local_providers.$name)($tcx, key)
303        } else {
304            ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
305        }
306    }};
307    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
308        call_provider!([$($modifiers)*][$($args)*])
309    };
310}
311
312macro_rules! should_ever_cache_on_disk {
313    ([]$yes:tt $no:tt) => {{
314        $no
315    }};
316    ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{
317        $yes
318    }};
319    ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => {
320        should_ever_cache_on_disk!([$($modifiers)*]$yes $no)
321    };
322}
323
324fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>(
325    (tcx, key, kind, name, do_describe): (
326        TyCtxt<'tcx>,
327        K,
328        DepKind,
329        &'static str,
330        fn(TyCtxt<'tcx>, K) -> String,
331    ),
332) -> QueryStackFrameExtra {
333    let def_id = key.key_as_def_id();
334
335    // If reduced queries are requested, we may be printing a query stack due
336    // to a panic. Avoid using `default_span` and `def_kind` in that case.
337    let reduce_queries = with_reduced_queries();
338
339    // Avoid calling queries while formatting the description
340    let description = ty::print::with_no_queries!(do_describe(tcx, key));
341    let description = if tcx.sess.verbose_internals() {
342        format!("{description} [{name:?}]")
343    } else {
344        description
345    };
346    let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries {
347        // The `def_span` query is used to calculate `default_span`,
348        // so exit to avoid infinite recursion.
349        None
350    } else {
351        Some(key.default_span(tcx))
352    };
353
354    let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries {
355        // Try to avoid infinite recursion.
356        None
357    } else {
358        def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
359    };
360    QueryStackFrameExtra::new(description, span, def_kind)
361}
362
363pub(crate) fn create_query_frame<
364    'tcx,
365    K: Copy + DynSend + DynSync + Key + for<'a> HashStable<StableHashingContext<'a>> + 'tcx,
366>(
367    tcx: TyCtxt<'tcx>,
368    do_describe: fn(TyCtxt<'tcx>, K) -> String,
369    key: K,
370    kind: DepKind,
371    name: &'static str,
372) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
373    let def_id = key.key_as_def_id();
374
375    let hash = || {
376        tcx.with_stable_hashing_context(|mut hcx| {
377            let mut hasher = StableHasher::new();
378            kind.as_usize().hash_stable(&mut hcx, &mut hasher);
379            key.hash_stable(&mut hcx, &mut hasher);
380            hasher.finish::<Hash64>()
381        })
382    };
383    let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
384
385    let info =
386        QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra);
387
388    QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
389}
390
391pub(crate) fn encode_query_results<'a, 'tcx, Q>(
392    query: Q::Config,
393    qcx: QueryCtxt<'tcx>,
394    encoder: &mut CacheEncoder<'a, 'tcx>,
395    query_result_index: &mut EncodedDepNodeIndex,
396) where
397    Q: super::QueryConfigRestored<'tcx>,
398    Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,
399{
400    let _timer = qcx.profiler().generic_activity_with_arg("encode_query_results_for", query.name());
401
402    assert!(query.query_state(qcx).all_inactive());
403    let cache = query.query_cache(qcx);
404    cache.iter(&mut |key, value, dep_node| {
405        if query.cache_on_disk(qcx.tcx, key) {
406            let dep_node = SerializedDepNodeIndex::new(dep_node.index());
407
408            // Record position of the cache entry.
409            query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
410
411            // Encode the type check tables with the `SerializedDepNodeIndex`
412            // as tag.
413            encoder.encode_tagged(dep_node, &Q::restore(*value));
414        }
415    });
416}
417
418pub(crate) fn query_key_hash_verify<'tcx>(
419    query: impl QueryConfig<QueryCtxt<'tcx>>,
420    qcx: QueryCtxt<'tcx>,
421) {
422    let _timer =
423        qcx.profiler().generic_activity_with_arg("query_key_hash_verify_for", query.name());
424
425    let mut map = UnordMap::default();
426
427    let cache = query.query_cache(qcx);
428    cache.iter(&mut |key, _, _| {
429        let node = DepNode::construct(qcx.tcx, query.dep_kind(), key);
430        if let Some(other_key) = map.insert(node, *key) {
431            bug!(
432                "query key:\n\
433                `{:?}`\n\
434                and key:\n\
435                `{:?}`\n\
436                mapped to the same dep node:\n\
437                {:?}",
438                key,
439                other_key,
440                node
441            );
442        }
443    });
444}
445
446fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
447where
448    Q: QueryConfig<QueryCtxt<'tcx>>,
449{
450    debug_assert!(tcx.dep_graph.is_green(&dep_node));
451
452    let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
453        panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
454    });
455    if query.cache_on_disk(tcx, &key) {
456        let _ = query.execute_query(tcx, key);
457    }
458}
459
460pub(crate) fn loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
461    if let Some(cache) = tcx.query_system.on_disk_cache.as_ref() {
462        cache.loadable_from_disk(id)
463    } else {
464        false
465    }
466}
467
468pub(crate) fn try_load_from_disk<'tcx, V>(
469    tcx: TyCtxt<'tcx>,
470    prev_index: SerializedDepNodeIndex,
471    index: DepNodeIndex,
472) -> Option<V>
473where
474    V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
475{
476    let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
477
478    let prof_timer = tcx.prof.incr_cache_loading();
479
480    // The call to `with_query_deserialization` enforces that no new `DepNodes`
481    // are created during deserialization. See the docs of that method for more
482    // details.
483    let value = tcx
484        .dep_graph
485        .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
486
487    prof_timer.finish_with_query_invocation_id(index.into());
488
489    value
490}
491
492fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
493where
494    Q: QueryConfig<QueryCtxt<'tcx>>,
495{
496    // We must avoid ever having to call `force_from_dep_node()` for a
497    // `DepNode::codegen_unit`:
498    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
499    // would always end up having to evaluate the first caller of the
500    // `codegen_unit` query that *is* reconstructible. This might very well be
501    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
502    // to re-trigger calling the `codegen_unit` query with the right key. At
503    // that point we would already have re-done all the work we are trying to
504    // avoid doing in the first place.
505    // The solution is simple: Just explicitly call the `codegen_unit` query for
506    // each CGU, right after partitioning. This way `try_mark_green` will always
507    // hit the cache instead of having to go through `force_from_dep_node`.
508    // This assertion makes sure, we actually keep applying the solution above.
509    debug_assert!(
510        dep_node.kind != dep_kinds::codegen_unit,
511        "calling force_from_dep_node() on dep_kinds::codegen_unit"
512    );
513
514    if let Some(key) = Q::Key::recover(tcx, &dep_node) {
515        force_query(query, QueryCtxt::new(tcx), key, dep_node);
516        true
517    } else {
518        false
519    }
520}
521
522pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
523where
524    Q: QueryConfigRestored<'tcx>,
525{
526    let fingerprint_style = <Q::Config as QueryConfig<QueryCtxt<'tcx>>>::Key::fingerprint_style();
527
528    if is_anon || !fingerprint_style.reconstructible() {
529        return DepKindStruct {
530            is_anon,
531            is_eval_always,
532            fingerprint_style,
533            force_from_dep_node: None,
534            try_load_from_on_disk_cache: None,
535            name: Q::NAME,
536        };
537    }
538
539    DepKindStruct {
540        is_anon,
541        is_eval_always,
542        fingerprint_style,
543        force_from_dep_node: Some(|tcx, dep_node, _| {
544            force_from_dep_node(Q::config(tcx), tcx, dep_node)
545        }),
546        try_load_from_on_disk_cache: Some(|tcx, dep_node| {
547            try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node)
548        }),
549        name: Q::NAME,
550    }
551}
552
553macro_rules! item_if_cached {
554    ([] $tokens:tt) => {};
555    ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
556        $($tokens)*
557    };
558    ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
559        item_if_cached! { [$($modifiers)*] $tokens }
560    };
561}
562
563macro_rules! expand_if_cached {
564    ([], $tokens:expr) => {{
565        None
566    }};
567    ([(cache) $($rest:tt)*], $tokens:expr) => {{
568        Some($tokens)
569    }};
570    ([$other:tt $($modifiers:tt)*], $tokens:expr) => {
571        expand_if_cached!([$($modifiers)*], $tokens)
572    };
573}
574
575/// Don't show the backtrace for query system by default
576/// use `RUST_BACKTRACE=full` to show all the backtraces
577#[inline(never)]
578pub(crate) fn __rust_begin_short_backtrace<F, T>(f: F) -> T
579where
580    F: FnOnce() -> T,
581{
582    let result = f();
583    std::hint::black_box(());
584    result
585}
586
587// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
588// invoked by `rustc_with_all_queries`.
589macro_rules! define_queries {
590    (
591        $(
592            $(#[$attr:meta])*
593            [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,
594        )*
595    ) => {
596
597        pub(crate) mod query_impl { $(pub(crate) mod $name {
598            use super::super::*;
599            use std::marker::PhantomData;
600
601            pub(crate) mod get_query_incr {
602                use super::*;
603
604                // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
605                // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
606                #[inline(never)]
607                pub(crate) fn __rust_end_short_backtrace<'tcx>(
608                    tcx: TyCtxt<'tcx>,
609                    span: Span,
610                    key: queries::$name::Key<'tcx>,
611                    mode: QueryMode,
612                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
613                    #[cfg(debug_assertions)]
614                    let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
615                    get_query_incr(
616                        QueryType::config(tcx),
617                        QueryCtxt::new(tcx),
618                        span,
619                        key,
620                        mode
621                    )
622                }
623            }
624
625            pub(crate) mod get_query_non_incr {
626                use super::*;
627
628                #[inline(never)]
629                pub(crate) fn __rust_end_short_backtrace<'tcx>(
630                    tcx: TyCtxt<'tcx>,
631                    span: Span,
632                    key: queries::$name::Key<'tcx>,
633                    __mode: QueryMode,
634                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
635                    Some(get_query_non_incr(
636                        QueryType::config(tcx),
637                        QueryCtxt::new(tcx),
638                        span,
639                        key,
640                    ))
641                }
642            }
643
644            pub(crate) fn dynamic_query<'tcx>()
645                -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>>
646            {
647                DynamicQuery {
648                    name: stringify!($name),
649                    eval_always: is_eval_always!([$($modifiers)*]),
650                    dep_kind: dep_graph::dep_kinds::$name,
651                    handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
652                    query_state: std::mem::offset_of!(QueryStates<'tcx>, $name),
653                    query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name),
654                    cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
655                    execute_query: |tcx, key| erase(tcx.$name(key)),
656                    compute: |tcx, key| {
657                        #[cfg(debug_assertions)]
658                        let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
659                        __rust_begin_short_backtrace(||
660                            queries::$name::provided_to_erased(
661                                tcx,
662                                {
663                                    let ret = call_provider!([$($modifiers)*][tcx, $name, key]);
664                                    rustc_middle::ty::print::with_reduced_queries!({
665                                        tracing::trace!(?ret);
666                                    });
667                                    ret
668                                }
669                            )
670                        )
671                    },
672                    can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
673                    try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
674                        |tcx, key, prev_index, index| {
675                            if ::rustc_middle::query::cached::$name(tcx, key) {
676                                let value = $crate::plumbing::try_load_from_disk::<
677                                    queries::$name::ProvidedValue<'tcx>
678                                >(
679                                    tcx,
680                                    prev_index,
681                                    index,
682                                );
683                                value.map(|value| queries::$name::provided_to_erased(tcx, value))
684                            } else {
685                                None
686                            }
687                        }
688                    } {
689                        |_tcx, _key, _prev_index, _index| None
690                    }),
691                    value_from_cycle_error: |tcx, cycle, guar| {
692                        let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar);
693                        erase(result)
694                    },
695                    loadable_from_disk: |_tcx, _key, _index| {
696                        should_ever_cache_on_disk!([$($modifiers)*] {
697                            ::rustc_middle::query::cached::$name(_tcx, _key) &&
698                                $crate::plumbing::loadable_from_disk(_tcx, _index)
699                        } {
700                            false
701                        })
702                    },
703                    hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
704                    format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
705                }
706            }
707
708            #[derive(Copy, Clone, Default)]
709            pub(crate) struct QueryType<'tcx> {
710                data: PhantomData<&'tcx ()>
711            }
712
713            impl<'tcx> QueryConfigRestored<'tcx> for QueryType<'tcx> {
714                type RestoredValue = queries::$name::Value<'tcx>;
715                type Config = DynamicConfig<
716                    'tcx,
717                    queries::$name::Storage<'tcx>,
718                    { is_anon!([$($modifiers)*]) },
719                    { depth_limit!([$($modifiers)*]) },
720                    { feedable!([$($modifiers)*]) },
721                >;
722
723                const NAME: &'static &'static str = &stringify!($name);
724
725                #[inline(always)]
726                fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
727                    DynamicConfig {
728                        dynamic: &tcx.query_system.dynamic_queries.$name,
729                    }
730                }
731
732                #[inline(always)]
733                fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
734                    restore::<queries::$name::Value<'tcx>>(value)
735                }
736            }
737
738            pub(crate) fn collect_active_jobs<'tcx>(
739                tcx: TyCtxt<'tcx>,
740                qmap: &mut QueryMap<QueryStackDeferred<'tcx>>,
741                require_complete: bool,
742            ) -> Option<()> {
743                let make_query = |tcx, key| {
744                    let kind = rustc_middle::dep_graph::dep_kinds::$name;
745                    let name = stringify!($name);
746                    $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
747                };
748                let res = tcx.query_system.states.$name.collect_active_jobs(
749                    tcx,
750                    make_query,
751                    qmap,
752                    require_complete,
753                );
754                // this can be called during unwinding, and the function has a `try_`-prefix, so
755                // don't `unwrap()` here, just manually check for `None` and do best-effort error
756                // reporting.
757                if res.is_none() {
758                    tracing::warn!(
759                        "Failed to collect active jobs for query with name `{}`!",
760                        stringify!($name)
761                    );
762                }
763                res
764            }
765
766            pub(crate) fn alloc_self_profile_query_strings<'tcx>(
767                tcx: TyCtxt<'tcx>,
768                string_cache: &mut QueryKeyStringCache
769            ) {
770                $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
771                    tcx,
772                    stringify!($name),
773                    &tcx.query_system.caches.$name,
774                    string_cache,
775                )
776            }
777
778            item_if_cached! { [$($modifiers)*] {
779                pub(crate) fn encode_query_results<'tcx>(
780                    tcx: TyCtxt<'tcx>,
781                    encoder: &mut CacheEncoder<'_, 'tcx>,
782                    query_result_index: &mut EncodedDepNodeIndex
783                ) {
784                    $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
785                        query_impl::$name::QueryType::config(tcx),
786                        QueryCtxt::new(tcx),
787                        encoder,
788                        query_result_index,
789                    )
790                }
791            }}
792
793            pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) {
794                $crate::plumbing::query_key_hash_verify(
795                    query_impl::$name::QueryType::config(tcx),
796                    QueryCtxt::new(tcx),
797                )
798            }
799        })*}
800
801        pub(crate) fn engine(incremental: bool) -> QueryEngine {
802            if incremental {
803                QueryEngine {
804                    $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
805                }
806            } else {
807                QueryEngine {
808                    $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
809                }
810            }
811        }
812
813        pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
814            DynamicQueries {
815                $(
816                    $name: query_impl::$name::dynamic_query(),
817                )*
818            }
819        }
820
821        // These arrays are used for iteration and can't be indexed by `DepKind`.
822
823        const COLLECT_ACTIVE_JOBS: &[
824            for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>, bool) -> Option<()>
825        ] =
826            &[$(query_impl::$name::collect_active_jobs),*];
827
828        const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
829            for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
830        ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
831
832        const ENCODE_QUERY_RESULTS: &[
833            Option<for<'tcx> fn(
834                TyCtxt<'tcx>,
835                &mut CacheEncoder<'_, 'tcx>,
836                &mut EncodedDepNodeIndex)
837            >
838        ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
839
840        const QUERY_KEY_HASH_VERIFY: &[
841            for<'tcx> fn(TyCtxt<'tcx>)
842        ] = &[$(query_impl::$name::query_key_hash_verify),*];
843
844        #[allow(nonstandard_style)]
845        mod query_callbacks {
846            use super::*;
847            use rustc_middle::bug;
848            use rustc_query_system::dep_graph::FingerprintStyle;
849
850            // We use this for most things when incr. comp. is turned off.
851            pub(crate) fn Null<'tcx>() -> DepKindStruct<'tcx> {
852                DepKindStruct {
853                    is_anon: false,
854                    is_eval_always: false,
855                    fingerprint_style: FingerprintStyle::Unit,
856                    force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
857                    try_load_from_on_disk_cache: None,
858                    name: &"Null",
859                }
860            }
861
862            // We use this for the forever-red node.
863            pub(crate) fn Red<'tcx>() -> DepKindStruct<'tcx> {
864                DepKindStruct {
865                    is_anon: false,
866                    is_eval_always: false,
867                    fingerprint_style: FingerprintStyle::Unit,
868                    force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
869                    try_load_from_on_disk_cache: None,
870                    name: &"Red",
871                }
872            }
873
874            pub(crate) fn SideEffect<'tcx>() -> DepKindStruct<'tcx> {
875                DepKindStruct {
876                    is_anon: false,
877                    is_eval_always: false,
878                    fingerprint_style: FingerprintStyle::Unit,
879                    force_from_dep_node: Some(|tcx, _, prev_index| {
880                        tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
881                        true
882                    }),
883                    try_load_from_on_disk_cache: None,
884                    name: &"SideEffect",
885                }
886            }
887
888            pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindStruct<'tcx> {
889                DepKindStruct {
890                    is_anon: true,
891                    is_eval_always: false,
892                    fingerprint_style: FingerprintStyle::Opaque,
893                    force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")),
894                    try_load_from_on_disk_cache: None,
895                    name: &"AnonZeroDeps",
896                }
897            }
898
899            pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
900                DepKindStruct {
901                    is_anon: true,
902                    is_eval_always: false,
903                    fingerprint_style: FingerprintStyle::Unit,
904                    force_from_dep_node: None,
905                    try_load_from_on_disk_cache: None,
906                    name: &"TraitSelect",
907                }
908            }
909
910            pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
911                DepKindStruct {
912                    is_anon: false,
913                    is_eval_always: false,
914                    fingerprint_style: FingerprintStyle::Opaque,
915                    force_from_dep_node: None,
916                    try_load_from_on_disk_cache: None,
917                    name: &"CompileCodegenUnit",
918                }
919            }
920
921            pub(crate) fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
922                DepKindStruct {
923                    is_anon: false,
924                    is_eval_always: false,
925                    fingerprint_style: FingerprintStyle::Opaque,
926                    force_from_dep_node: None,
927                    try_load_from_on_disk_cache: None,
928                    name: &"CompileMonoItem",
929                }
930            }
931
932            pub(crate) fn Metadata<'tcx>() -> DepKindStruct<'tcx> {
933                DepKindStruct {
934                    is_anon: false,
935                    is_eval_always: false,
936                    fingerprint_style: FingerprintStyle::Unit,
937                    force_from_dep_node: None,
938                    try_load_from_on_disk_cache: None,
939                    name: &"Metadata",
940                }
941            }
942
943            $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
944                $crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
945                    is_anon!([$($modifiers)*]),
946                    is_eval_always!([$($modifiers)*]),
947                )
948            })*
949        }
950
951        pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
952            arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(query_callbacks))
953        }
954
955        pub fn dep_kind_names() -> Vec<&'static str> {
956            rustc_middle::make_dep_kind_name_array!(query_callbacks)
957        }
958    }
959}