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