Skip to main content

rustc_middle/query/
plumbing.rs

1use std::fmt;
2use std::ops::Deref;
3
4use rustc_data_structures::fingerprint::Fingerprint;
5use rustc_data_structures::hash_table::HashTable;
6use rustc_data_structures::sharded::Sharded;
7use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
8use rustc_errors::Diag;
9use rustc_span::Span;
10
11use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
12use crate::ich::StableHashingContext;
13use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
14use crate::query::on_disk_cache::OnDiskCache;
15use crate::query::{QueryCache, QueryJob, QueryStackFrame};
16use crate::ty::TyCtxt;
17
18/// For a particular query, keeps track of "active" keys, i.e. keys whose
19/// evaluation has started but has not yet finished successfully.
20///
21/// (Successful query evaluation for a key is represented by an entry in the
22/// query's in-memory cache.)
23pub struct QueryState<'tcx, K> {
24    pub active: Sharded<HashTable<(K, ActiveKeyStatus<'tcx>)>>,
25}
26
27impl<'tcx, K> Default for QueryState<'tcx, K> {
28    fn default() -> QueryState<'tcx, K> {
29        QueryState { active: Default::default() }
30    }
31}
32
33/// For a particular query and key, tracks the status of a query evaluation
34/// that has started, but has not yet finished successfully.
35///
36/// (Successful query evaluation for a key is represented by an entry in the
37/// query's in-memory cache.)
38pub enum ActiveKeyStatus<'tcx> {
39    /// Some thread is already evaluating the query for this key.
40    ///
41    /// The enclosed [`QueryJob`] can be used to wait for it to finish.
42    Started(QueryJob<'tcx>),
43
44    /// The query panicked. Queries trying to wait on this will raise a fatal error which will
45    /// silently panic.
46    Poisoned,
47}
48
49#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for CycleError<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "CycleError",
            "usage", &self.usage, "cycle", &&self.cycle)
    }
}Debug)]
50pub struct CycleError<'tcx> {
51    /// The query and related span that uses the cycle.
52    pub usage: Option<QueryStackFrame<'tcx>>,
53
54    /// The span here corresponds to the reason for which this query was required.
55    pub cycle: Vec<QueryStackFrame<'tcx>>,
56}
57
58#[derive(#[automatically_derived]
impl ::core::fmt::Debug for QueryMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            QueryMode::Get => ::core::fmt::Formatter::write_str(f, "Get"),
            QueryMode::Ensure { ensure_mode: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Ensure", "ensure_mode", &__self_0),
        }
    }
}Debug)]
59pub enum QueryMode {
60    /// This is a normal query call to `tcx.$query(..)` or `tcx.at(span).$query(..)`.
61    Get,
62    /// This is a call to `tcx.ensure_ok().$query(..)` or `tcx.ensure_done().$query(..)`.
63    Ensure { ensure_mode: EnsureMode },
64}
65
66/// Distinguishes between `tcx.ensure_ok()` and `tcx.ensure_done()` in shared
67/// code paths that handle both modes.
68#[derive(#[automatically_derived]
impl ::core::fmt::Debug for EnsureMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                EnsureMode::Ok => "Ok",
                EnsureMode::Done => "Done",
            })
    }
}Debug)]
69pub enum EnsureMode {
70    /// Corresponds to [`TyCtxt::ensure_ok`].
71    Ok,
72    /// Corresponds to [`TyCtxt::ensure_done`].
73    Done,
74}
75
76/// Stores data and metadata (e.g. function pointers) for a particular query.
77pub struct QueryVTable<'tcx, C: QueryCache> {
78    pub name: &'static str,
79
80    /// True if this query has the `anon` modifier.
81    pub anon: bool,
82    /// True if this query has the `eval_always` modifier.
83    pub eval_always: bool,
84    /// True if this query has the `depth_limit` modifier.
85    pub depth_limit: bool,
86    /// True if this query has the `feedable` modifier.
87    pub feedable: bool,
88
89    pub dep_kind: DepKind,
90    pub state: QueryState<'tcx, C::Key>,
91    pub cache: C,
92
93    /// Function pointer that actually calls this query's provider.
94    /// Also performs some associated secondary tasks; see the macro-defined
95    /// implementation in `mod invoke_provider_fn` for more details.
96    ///
97    /// This should be the only code that calls the provider function.
98    pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
99
100    pub will_cache_on_disk_for_key_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> bool,
101
102    pub try_load_from_disk_fn: fn(
103        tcx: TyCtxt<'tcx>,
104        key: C::Key,
105        prev_index: SerializedDepNodeIndex,
106        index: DepNodeIndex,
107    ) -> Option<C::Value>,
108
109    pub is_loadable_from_disk_fn:
110        fn(tcx: TyCtxt<'tcx>, key: C::Key, index: SerializedDepNodeIndex) -> bool,
111
112    /// Function pointer that hashes this query's result values.
113    ///
114    /// For `no_hash` queries, this function pointer is None.
115    pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
116
117    /// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if
118    /// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative
119    /// error is created and emitted).
120    pub value_from_cycle_error: fn(
121        tcx: TyCtxt<'tcx>,
122        key: C::Key,
123        cycle_error: CycleError<'tcx>,
124        error: Diag<'_>,
125    ) -> C::Value,
126
127    pub format_value: fn(&C::Value) -> String,
128
129    pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>,
130
131    /// Function pointer that is called by the query methods on [`TyCtxt`] and
132    /// friends[^1], after they have checked the in-memory cache and found no
133    /// existing value for this key.
134    ///
135    /// Transitive responsibilities include trying to load a disk-cached value
136    /// if possible (incremental only), invoking the query provider if necessary,
137    /// and putting the obtained value into the in-memory cache.
138    ///
139    /// [^1]: [`TyCtxt`], [`TyCtxtAt`], [`TyCtxtEnsureOk`], [`TyCtxtEnsureDone`]
140    pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
141}
142
143impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> {
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        // When debug-printing a query vtable (e.g. for ICE or tracing),
146        // just print the query name to know what query we're dealing with.
147        // The other fields and flags are probably just unhelpful noise.
148        //
149        // If there is need for a more detailed dump of all flags and fields,
150        // consider writing a separate dump method and calling it explicitly.
151        f.write_str(self.name)
152    }
153}
154
155pub struct QuerySystem<'tcx> {
156    pub arenas: WorkerLocal<QueryArenas<'tcx>>,
157    pub query_vtables: QueryVTables<'tcx>,
158
159    /// This provides access to the incremental compilation on-disk cache for query results.
160    /// Do not access this directly. It is only meant to be used by
161    /// `DepGraph::try_mark_green()` and the query infrastructure.
162    /// This is `None` if we are not incremental compilation mode
163    pub on_disk_cache: Option<OnDiskCache>,
164
165    pub local_providers: Providers,
166    pub extern_providers: ExternProviders,
167
168    pub jobs: AtomicU64,
169}
170
171#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for TyCtxtAt<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TyCtxtAt<'tcx> {
    #[inline]
    fn clone(&self) -> TyCtxtAt<'tcx> {
        let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone)]
172pub struct TyCtxtAt<'tcx> {
173    pub tcx: TyCtxt<'tcx>,
174    pub span: Span,
175}
176
177impl<'tcx> Deref for TyCtxtAt<'tcx> {
178    type Target = TyCtxt<'tcx>;
179    #[inline(always)]
180    fn deref(&self) -> &Self::Target {
181        &self.tcx
182    }
183}
184
185#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for TyCtxtEnsureOk<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TyCtxtEnsureOk<'tcx> {
    #[inline]
    fn clone(&self) -> TyCtxtEnsureOk<'tcx> {
        let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
        *self
    }
}Clone)]
186#[must_use]
187pub struct TyCtxtEnsureOk<'tcx> {
188    pub tcx: TyCtxt<'tcx>,
189}
190
191#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for TyCtxtEnsureResult<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TyCtxtEnsureResult<'tcx> {
    #[inline]
    fn clone(&self) -> TyCtxtEnsureResult<'tcx> {
        let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
        *self
    }
}Clone)]
192#[must_use]
193pub struct TyCtxtEnsureResult<'tcx> {
194    pub tcx: TyCtxt<'tcx>,
195}
196
197#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for TyCtxtEnsureDone<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TyCtxtEnsureDone<'tcx> {
    #[inline]
    fn clone(&self) -> TyCtxtEnsureDone<'tcx> {
        let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
        *self
    }
}Clone)]
198#[must_use]
199pub struct TyCtxtEnsureDone<'tcx> {
200    pub tcx: TyCtxt<'tcx>,
201}
202
203impl<'tcx> TyCtxt<'tcx> {
204    /// FIXME: `ensure_ok`'s effects are subtle. Is this comment fully accurate?
205    ///
206    /// Wrapper that calls queries in a special "ensure OK" mode, for callers
207    /// that don't need the return value and just want to invoke a query for
208    /// its potential side-effect of emitting fatal errors.
209    ///
210    /// This can be more efficient than a normal query call, because if the
211    /// query's inputs are all green, the call can return immediately without
212    /// needing to obtain a value (by decoding one from disk or by executing
213    /// the query).
214    ///
215    /// (As with all query calls, execution is also skipped if the query result
216    /// is already cached in memory.)
217    ///
218    /// ## WARNING
219    /// A subsequent normal call to the same query might still cause it to be
220    /// executed! This can occur when the inputs are all green, but the query's
221    /// result is not cached on disk, so the query must be executed to obtain a
222    /// return value.
223    ///
224    /// Therefore, this call mode is not appropriate for callers that want to
225    /// ensure that the query is _never_ executed in the future.
226    #[inline(always)]
227    pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> {
228        TyCtxtEnsureOk { tcx: self }
229    }
230
231    /// This is a variant of `ensure_ok` only usable with queries that return
232    /// `Result<_, ErrorGuaranteed>`. Queries calls through this function will
233    /// return `Result<(), ErrorGuaranteed>`. I.e. the error status is returned
234    /// but nothing else. As with `ensure_ok`, this can be more efficient than
235    /// a normal query call.
236    #[inline(always)]
237    pub fn ensure_result(self) -> TyCtxtEnsureResult<'tcx> {
238        TyCtxtEnsureResult { tcx: self }
239    }
240
241    /// Wrapper that calls queries in a special "ensure done" mode, for callers
242    /// that don't need the return value and just want to guarantee that the
243    /// query won't be executed in the future, by executing it now if necessary.
244    ///
245    /// This is useful for queries that read from a [`Steal`] value, to ensure
246    /// that they are executed before the query that will steal the value.
247    ///
248    /// Unlike [`Self::ensure_ok`], a query with all-green inputs will only be
249    /// skipped if its return value is stored in the disk-cache. This is still
250    /// more efficient than a regular query, because in that situation the
251    /// return value doesn't necessarily need to be decoded.
252    ///
253    /// (As with all query calls, execution is also skipped if the query result
254    /// is already cached in memory.)
255    ///
256    /// [`Steal`]: rustc_data_structures::steal::Steal
257    #[inline(always)]
258    pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> {
259        TyCtxtEnsureDone { tcx: self }
260    }
261
262    /// Returns a transparent wrapper for `TyCtxt` which uses
263    /// `span` as the location of queries performed through it.
264    #[inline(always)]
265    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
266        TyCtxtAt { tcx: self, span }
267    }
268}
269
270macro_rules! query_helper_param_ty {
271    (DefId) => { impl $crate::query::IntoQueryKey<DefId> };
272    (LocalDefId) => { impl $crate::query::IntoQueryKey<LocalDefId> };
273    ($K:ty) => { $K };
274}
275
276macro_rules! define_callbacks {
277    (
278        // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
279        // `query_helper_param_ty!` can match on specific type names.
280        queries {
281            $(
282                $(#[$attr:meta])*
283                fn $name:ident($($K:tt)*) -> $V:ty
284                {
285                    // Search for (QMODLIST) to find all occurrences of this query modifier list.
286                    anon: $anon:literal,
287                    arena_cache: $arena_cache:literal,
288                    cache_on_disk: $cache_on_disk:literal,
289                    depth_limit: $depth_limit:literal,
290                    eval_always: $eval_always:literal,
291                    feedable: $feedable:literal,
292                    no_hash: $no_hash:literal,
293                    returns_error_guaranteed: $returns_error_guaranteed:literal,
294                    separate_provide_extern: $separate_provide_extern:literal,
295                }
296            )*
297        }
298        // Non-queries are unused here.
299        non_queries { $($_:tt)* }
300    ) => {
301        $(
302            pub mod $name {
303                use super::*;
304                use $crate::query::erase::{self, Erased};
305
306                pub type Key<'tcx> = $($K)*;
307                pub type Value<'tcx> = $V;
308
309                /// Key type used by provider functions in `local_providers`.
310                /// This query has the `separate_provide_extern` modifier.
311                #[cfg($separate_provide_extern)]
312                pub type LocalKey<'tcx> =
313                    <Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey;
314                /// Key type used by provider functions in `local_providers`.
315                #[cfg(not($separate_provide_extern))]
316                pub type LocalKey<'tcx> = Key<'tcx>;
317
318                /// Type returned from query providers and loaded from disk-cache.
319                #[cfg($arena_cache)]
320                pub type ProvidedValue<'tcx> =
321                    <Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided;
322                /// Type returned from query providers and loaded from disk-cache.
323                #[cfg(not($arena_cache))]
324                pub type ProvidedValue<'tcx> = Value<'tcx>;
325
326                /// This helper function takes a value returned by the query provider
327                /// (or loaded from disk, or supplied by query feeding), allocates
328                /// it in an arena if requested by the `arena_cache` modifier, and
329                /// then returns an erased copy of it.
330                #[inline(always)]
331                pub fn provided_to_erased<'tcx>(
332                    tcx: TyCtxt<'tcx>,
333                    provided_value: ProvidedValue<'tcx>,
334                ) -> Erased<Value<'tcx>> {
335                    // For queries with the `arena_cache` modifier, store the
336                    // provided value in an arena and get a reference to it.
337                    #[cfg($arena_cache)]
338                    let value: Value<'tcx> = {
339                        use $crate::query::arena_cached::ArenaCached;
340                        <Value<'tcx> as ArenaCached>::alloc_in_arena(
341                            tcx,
342                            &tcx.query_system.arenas.$name,
343                            provided_value,
344                        )
345                    };
346
347                    // Otherwise, the provided value is the value (and `tcx` is unused).
348                    #[cfg(not($arena_cache))]
349                    let value: Value<'tcx> = {
350                        let _ = tcx;
351                        provided_value
352                    };
353
354                    erase::erase_val(value)
355                }
356
357                pub type Cache<'tcx> =
358                    <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
359
360                // Ensure that keys grow no larger than 88 bytes by accident.
361                // Increase this limit if necessary, but do try to keep the size low if possible
362                #[cfg(target_pointer_width = "64")]
363                const _: () = {
364                    if size_of::<Key<'static>>() > 88 {
365                        panic!("{}", concat!(
366                            "the query `",
367                            stringify!($name),
368                            "` has a key type `",
369                            stringify!($($K)*),
370                            "` that is too large"
371                        ));
372                    }
373                };
374
375                // Ensure that values grow no larger than 64 bytes by accident.
376                // Increase this limit if necessary, but do try to keep the size low if possible
377                #[cfg(target_pointer_width = "64")]
378                #[cfg(not(feature = "rustc_randomized_layouts"))]
379                const _: () = {
380                    if size_of::<Value<'static>>() > 64 {
381                        panic!("{}", concat!(
382                            "the query `",
383                            stringify!($name),
384                            "` has a value type `",
385                            stringify!($V),
386                            "` that is too large"
387                        ));
388                    }
389                };
390            }
391        )*
392
393        /// Holds per-query arenas for queries with the `arena_cache` modifier.
394        #[derive(Default)]
395        pub struct QueryArenas<'tcx> {
396            $(
397                // Use the `ArenaCached` helper trait to determine the arena's value type.
398                #[cfg($arena_cache)]
399                pub $name: TypedArena<
400                    <$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
401                >,
402            )*
403        }
404
405        impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
406            $(
407                $(#[$attr])*
408                #[inline(always)]
409                pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
410                    crate::query::inner::query_ensure_ok_or_done(
411                        self.tcx,
412                        &self.tcx.query_system.query_vtables.$name,
413                        $crate::query::IntoQueryKey::into_query_key(key),
414                        $crate::query::EnsureMode::Ok,
415                    )
416                }
417            )*
418        }
419
420        // Only defined when the `ensure_result` modifier is present.
421        impl<'tcx> $crate::query::TyCtxtEnsureResult<'tcx> {
422            $(
423                #[cfg($returns_error_guaranteed)]
424                $(#[$attr])*
425                #[inline(always)]
426                pub fn $name(
427                    self,
428                    key: query_helper_param_ty!($($K)*),
429                ) -> Result<(), rustc_errors::ErrorGuaranteed> {
430                    crate::query::inner::query_ensure_result(
431                        self.tcx,
432                        &self.tcx.query_system.query_vtables.$name,
433                        $crate::query::IntoQueryKey::into_query_key(key),
434                    )
435                }
436            )*
437        }
438
439        impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
440            $(
441                $(#[$attr])*
442                #[inline(always)]
443                pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
444                    crate::query::inner::query_ensure_ok_or_done(
445                        self.tcx,
446                        &self.tcx.query_system.query_vtables.$name,
447                        $crate::query::IntoQueryKey::into_query_key(key),
448                        $crate::query::EnsureMode::Done,
449                    );
450                }
451            )*
452        }
453
454        impl<'tcx> TyCtxt<'tcx> {
455            $(
456                $(#[$attr])*
457                #[inline(always)]
458                #[must_use]
459                pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
460                    self.at(DUMMY_SP).$name(key)
461                }
462            )*
463        }
464
465        impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
466            $(
467                $(#[$attr])*
468                #[inline(always)]
469                pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
470                    use $crate::query::{erase, inner};
471
472                    erase::restore_val::<$V>(inner::query_get_at(
473                        self.tcx,
474                        self.span,
475                        &self.tcx.query_system.query_vtables.$name,
476                        $crate::query::IntoQueryKey::into_query_key(key),
477                    ))
478                }
479            )*
480        }
481
482        $(
483            #[cfg($feedable)]
484            impl<'tcx, K: $crate::query::IntoQueryKey<$name::Key<'tcx>> + Copy>
485                TyCtxtFeed<'tcx, K>
486            {
487                $(#[$attr])*
488                #[inline(always)]
489                pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
490                    let key = self.key().into_query_key();
491                    let erased_value = $name::provided_to_erased(self.tcx, value);
492                    $crate::query::inner::query_feed(
493                        self.tcx,
494                        &self.tcx.query_system.query_vtables.$name,
495                        key,
496                        erased_value,
497                    );
498                }
499            }
500        )*
501
502        /// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a number.
503        #[allow(non_camel_case_types)]
504        #[derive(Clone, Copy, Debug)]
505        pub enum TaggedQueryKey<'tcx> {
506            $(
507                $name($name::Key<'tcx>),
508            )*
509        }
510
511        impl<'tcx> TaggedQueryKey<'tcx> {
512            /// Returns the name of the query this key is tagged with.
513            ///
514            /// This is useful for error/debug output, but don't use it to check for
515            /// specific query names. Instead, match on the `TaggedQueryKey` variant.
516            pub fn query_name(&self) -> &'static str {
517                match self {
518                    $(
519                        TaggedQueryKey::$name(_) => stringify!($name),
520                    )*
521                }
522            }
523
524            /// Formats a human-readable description of this query and its key, as
525            /// specified by the `desc` query modifier.
526            ///
527            /// Used when reporting query cycle errors and similar problems.
528            pub fn description(&self, tcx: TyCtxt<'tcx>) -> String {
529                let (name, description) = ty::print::with_no_queries!(match self {
530                    $(
531                        TaggedQueryKey::$name(key) => (stringify!($name), _description_fns::$name(tcx, *key)),
532                    )*
533                });
534                if tcx.sess.verbose_internals() {
535                    format!("{description} [{name:?}]")
536                } else {
537                    description
538                }
539            }
540
541            /// Returns the default span for this query if `span` is a dummy span.
542            pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
543                if !span.is_dummy() {
544                    return span
545                }
546                if let TaggedQueryKey::def_span(..) = self {
547                    // The `def_span` query is used to calculate `default_span`,
548                    // so exit to avoid infinite recursion.
549                    return DUMMY_SP
550                }
551                match self {
552                    $(
553                        TaggedQueryKey::$name(key) => crate::query::QueryKey::default_span(key, tcx),
554                    )*
555                }
556            }
557
558            pub fn def_kind(&self, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
559                // This is used to reduce code generation as it
560                // can be reused for queries with the same key type.
561                fn inner<'tcx>(key: &impl crate::query::QueryKey, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
562                    key.key_as_def_id().and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
563                }
564
565                if let TaggedQueryKey::def_kind(..) = self {
566                    // Try to avoid infinite recursion.
567                    return None
568                }
569                match self {
570                    $(
571                        TaggedQueryKey::$name(key) => inner(key, tcx),
572                    )*
573                }
574            }
575        }
576
577        /// Holds a `QueryVTable` for each query.
578        pub struct QueryVTables<'tcx> {
579            $(
580                pub $name: crate::query::QueryVTable<'tcx, $name::Cache<'tcx>>,
581            )*
582        }
583
584        pub struct Providers {
585            $(
586                /// This is the provider for the query. Use `Find references` on this to
587                /// navigate between the provider assignment and the query definition.
588                pub $name: for<'tcx> fn(
589                    TyCtxt<'tcx>,
590                    $name::LocalKey<'tcx>,
591                ) -> $name::ProvidedValue<'tcx>,
592            )*
593        }
594
595        pub struct ExternProviders {
596            $(
597                #[cfg($separate_provide_extern)]
598                pub $name: for<'tcx> fn(
599                    TyCtxt<'tcx>,
600                    $name::Key<'tcx>,
601                ) -> $name::ProvidedValue<'tcx>,
602            )*
603        }
604
605        impl Default for Providers {
606            fn default() -> Self {
607                Providers {
608                    $(
609                        $name: |_, key| {
610                            $crate::query::plumbing::default_query(stringify!($name), &key)
611                        },
612                    )*
613                }
614            }
615        }
616
617        impl Default for ExternProviders {
618            fn default() -> Self {
619                ExternProviders {
620                    $(
621                        #[cfg($separate_provide_extern)]
622                        $name: |_, key| $crate::query::plumbing::default_extern_query(
623                            stringify!($name),
624                            &key,
625                        ),
626                    )*
627                }
628            }
629        }
630
631        impl Copy for Providers {}
632        impl Clone for Providers {
633            fn clone(&self) -> Self { *self }
634        }
635
636        impl Copy for ExternProviders {}
637        impl Clone for ExternProviders {
638            fn clone(&self) -> Self { *self }
639        }
640    };
641}
642
643// Re-export `macro_rules!` macros as normal items, so that they can be imported normally.
644pub(crate) use define_callbacks;
645pub(crate) use query_helper_param_ty;
646
647#[cold]
648pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
649    crate::util::bug::bug_fmt(format_args!("`tcx.{0}({1:?})` is not supported for this key;\nhint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that\'s not supported.\nIf that\'s not the case, {0} was likely never assigned to a provider function.\n",
        name, key))bug!(
650        "`tcx.{name}({key:?})` is not supported for this key;\n\
651        hint: Queries can be either made to the local crate, or the external crate. \
652        This error means you tried to use it for one that's not supported.\n\
653        If that's not the case, {name} was likely never assigned to a provider function.\n",
654    )
655}
656
657#[cold]
658pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
659    crate::util::bug::bug_fmt(format_args!("`tcx.{0}({1:?})` unsupported by its crate; perhaps the `{0}` query was never assigned a provider function",
        name, key))bug!(
660        "`tcx.{name}({key:?})` unsupported by its crate; \
661         perhaps the `{name}` query was never assigned a provider function",
662    )
663}