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::StableHashingContext;
15use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
16use crate::query::on_disk_cache::OnDiskCache;
17use crate::query::{IntoQueryKey, QueryCache, QueryJob, 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 {
        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)]
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(..)` or `tcx.ensure_done().$query(..)`.
65    Ensure { ensure_mode: EnsureMode },
66}
67
68/// Distinguishes between `tcx.ensure_ok()` and `tcx.ensure_done()` in shared
69/// code paths that handle both modes.
70#[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)]
71pub enum EnsureMode {
72    /// Corresponds to [`TyCtxt::ensure_ok`].
73    Ok,
74    /// Corresponds to [`TyCtxt::ensure_done`].
75    Done,
76}
77
78/// Stores data and metadata (e.g. function pointers) for a particular query.
79pub struct QueryVTable<'tcx, C: QueryCache> {
80    pub name: &'static str,
81
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(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    /// Function pointer that hashes this query's result values.
110    ///
111    /// For `no_hash` queries, this function pointer is None.
112    pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
113
114    /// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if
115    /// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative
116    /// error is created and emitted). A value may be returned, or (more commonly) the function may
117    /// just abort after emitting the error.
118    pub handle_cycle_error_fn:
119        fn(tcx: TyCtxt<'tcx>, key: C::Key, cycle: Cycle<'tcx>, error: Diag<'_>) -> C::Value,
120
121    pub format_value: fn(&C::Value) -> String,
122
123    pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>,
124
125    /// Function pointer that is called by the query methods on [`TyCtxt`] and
126    /// friends[^1], after they have checked the in-memory cache and found no
127    /// existing value for this key.
128    ///
129    /// Transitive responsibilities include trying to load a disk-cached value
130    /// if possible (incremental only), invoking the query provider if necessary,
131    /// and putting the obtained value into the in-memory cache.
132    ///
133    /// [^1]: [`TyCtxt`], [`TyCtxtAt`], [`TyCtxtEnsureOk`], [`TyCtxtEnsureDone`]
134    pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
135}
136
137impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        // When debug-printing a query vtable (e.g. for ICE or tracing),
140        // just print the query name to know what query we're dealing with.
141        // The other fields and flags are probably just unhelpful noise.
142        //
143        // If there is need for a more detailed dump of all flags and fields,
144        // consider writing a separate dump method and calling it explicitly.
145        f.write_str(self.name)
146    }
147}
148
149pub struct QuerySystem<'tcx> {
150    pub arenas: WorkerLocal<QueryArenas<'tcx>>,
151    pub query_vtables: QueryVTables<'tcx>,
152
153    /// Side-effect associated with each [`DepKind::SideEffect`] node in the
154    /// current incremental-compilation session. Side effects will be written
155    /// to disk, and loaded by [`OnDiskCache`] in the next session.
156    ///
157    /// Always empty if incremental compilation is off.
158    pub side_effects: Lock<FxIndexMap<DepNodeIndex, QuerySideEffect>>,
159
160    /// This provides access to the incremental compilation on-disk cache for query results.
161    /// Do not access this directly. It is only meant to be used by
162    /// `DepGraph::try_mark_green()` and the query infrastructure.
163    /// This is `None` if we are not incremental compilation mode
164    pub on_disk_cache: Option<OnDiskCache>,
165
166    pub local_providers: Providers,
167    pub extern_providers: ExternProviders,
168
169    pub jobs: AtomicU64,
170}
171
172#[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)]
173pub struct TyCtxtAt<'tcx> {
174    pub tcx: TyCtxt<'tcx>,
175    pub span: Span,
176}
177
178impl<'tcx> Deref for TyCtxtAt<'tcx> {
179    type Target = TyCtxt<'tcx>;
180    #[inline(always)]
181    fn deref(&self) -> &Self::Target {
182        &self.tcx
183    }
184}
185
186#[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)]
187#[must_use]
188pub struct TyCtxtEnsureOk<'tcx> {
189    pub tcx: TyCtxt<'tcx>,
190}
191
192#[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)]
193#[must_use]
194pub struct TyCtxtEnsureResult<'tcx> {
195    pub tcx: TyCtxt<'tcx>,
196}
197
198#[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)]
199#[must_use]
200pub struct TyCtxtEnsureDone<'tcx> {
201    pub tcx: TyCtxt<'tcx>,
202}
203
204impl<'tcx> TyCtxtEnsureOk<'tcx> {
205    pub fn typeck(self, def_id: impl IntoQueryKey<LocalDefId>) {
206        self.typeck_root(
207            self.tcx.typeck_root_def_id(def_id.into_query_key().to_def_id()).expect_local(),
208        )
209    }
210}
211
212impl<'tcx> TyCtxt<'tcx> {
213    pub fn typeck(self, def_id: impl IntoQueryKey<LocalDefId>) -> &'tcx ty::TypeckResults<'tcx> {
214        self.typeck_root(
215            self.typeck_root_def_id(def_id.into_query_key().to_def_id()).expect_local(),
216        )
217    }
218
219    /// Returns a transparent wrapper for `TyCtxt` which uses
220    /// `span` as the location of queries performed through it.
221    #[inline(always)]
222    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
223        TyCtxtAt { tcx: self, span }
224    }
225
226    /// FIXME: `ensure_ok`'s effects are subtle. Is this comment fully accurate?
227    ///
228    /// Wrapper that calls queries in a special "ensure OK" mode, for callers
229    /// that don't need the return value and just want to invoke a query for
230    /// its potential side-effect of emitting fatal errors.
231    ///
232    /// This can be more efficient than a normal query call, because if the
233    /// query's inputs are all green, the call can return immediately without
234    /// needing to obtain a value (by decoding one from disk or by executing
235    /// the query).
236    ///
237    /// (As with all query calls, execution is also skipped if the query result
238    /// is already cached in memory.)
239    ///
240    /// ## WARNING
241    /// A subsequent normal call to the same query might still cause it to be
242    /// executed! This can occur when the inputs are all green, but the query's
243    /// result is not cached on disk, so the query must be executed to obtain a
244    /// return value.
245    ///
246    /// Therefore, this call mode is not appropriate for callers that want to
247    /// ensure that the query is _never_ executed in the future.
248    #[inline(always)]
249    pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> {
250        TyCtxtEnsureOk { tcx: self }
251    }
252
253    /// This is a variant of `ensure_ok` only usable with queries that return
254    /// `Result<_, ErrorGuaranteed>`. Queries calls through this function will
255    /// return `Result<(), ErrorGuaranteed>`. I.e. the error status is returned
256    /// but nothing else. As with `ensure_ok`, this can be more efficient than
257    /// a normal query call.
258    #[inline(always)]
259    pub fn ensure_result(self) -> TyCtxtEnsureResult<'tcx> {
260        TyCtxtEnsureResult { tcx: self }
261    }
262
263    /// Wrapper that calls queries in a special "ensure done" mode, for callers
264    /// that don't need the return value and just want to guarantee that the
265    /// query won't be executed in the future, by executing it now if necessary.
266    ///
267    /// This is useful for queries that read from a [`Steal`] value, to ensure
268    /// that they are executed before the query that will steal the value.
269    ///
270    /// Unlike [`Self::ensure_ok`], a query with all-green inputs will only be
271    /// skipped if its return value is stored in the disk-cache. This is still
272    /// more efficient than a regular query, because in that situation the
273    /// return value doesn't necessarily need to be decoded.
274    ///
275    /// (As with all query calls, execution is also skipped if the query result
276    /// is already cached in memory.)
277    ///
278    /// [`Steal`]: rustc_data_structures::steal::Steal
279    #[inline(always)]
280    pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> {
281        TyCtxtEnsureDone { tcx: self }
282    }
283}
284
285macro_rules! maybe_into_query_key {
286    (DefId) => { impl $crate::query::IntoQueryKey<DefId> };
287    (LocalDefId) => { impl $crate::query::IntoQueryKey<LocalDefId> };
288    ($K:ty) => { $K };
289}
290
291macro_rules! define_callbacks {
292    (
293        // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
294        // `maybe_into_query_key!` can match on specific type names.
295        queries {
296            $(
297                $(#[$attr:meta])*
298                fn $name:ident($($K:tt)*) -> $V:ty
299                {
300                    // Search for (QMODLIST) to find all occurrences of this query modifier list.
301                    arena_cache: $arena_cache:literal,
302                    cache_on_disk: $cache_on_disk:literal,
303                    depth_limit: $depth_limit:literal,
304                    desc: $desc:expr,
305                    eval_always: $eval_always:literal,
306                    feedable: $feedable:literal,
307                    handle_cycle_error: $handle_cycle_error:literal,
308                    no_force: $no_force:literal,
309                    no_hash: $no_hash:literal,
310                    returns_error_guaranteed: $returns_error_guaranteed:literal,
311                    separate_provide_extern: $separate_provide_extern:literal,
312                }
313            )*
314        }
315        // Non-queries are unused here.
316        non_queries { $($_:tt)* }
317    ) => {
318        $(
319            pub mod $name {
320                use super::*;
321                use $crate::query::erase::{self, Erased};
322
323                pub type Key<'tcx> = $($K)*;
324                pub type Value<'tcx> = $V;
325
326                /// Key type used by provider functions in `local_providers`.
327                /// This query has the `separate_provide_extern` modifier.
328                #[cfg($separate_provide_extern)]
329                pub type LocalKey<'tcx> =
330                    <Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey;
331                /// Key type used by provider functions in `local_providers`.
332                #[cfg(not($separate_provide_extern))]
333                pub type LocalKey<'tcx> = Key<'tcx>;
334
335                /// Type returned from query providers and loaded from disk-cache.
336                #[cfg($arena_cache)]
337                pub type ProvidedValue<'tcx> =
338                    <Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided;
339                /// Type returned from query providers and loaded from disk-cache.
340                #[cfg(not($arena_cache))]
341                pub type ProvidedValue<'tcx> = Value<'tcx>;
342
343                pub type Cache<'tcx> =
344                    <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
345
346                /// This helper function takes a value returned by the query provider
347                /// (or loaded from disk, or supplied by query feeding), allocates
348                /// it in an arena if requested by the `arena_cache` modifier, and
349                /// then returns an erased copy of it.
350                #[inline(always)]
351                pub fn provided_to_erased<'tcx>(
352                    tcx: TyCtxt<'tcx>,
353                    provided_value: ProvidedValue<'tcx>,
354                ) -> Erased<Value<'tcx>> {
355                    // For queries with the `arena_cache` modifier, store the
356                    // provided value in an arena and get a reference to it.
357                    #[cfg($arena_cache)]
358                    let value: Value<'tcx> = {
359                        use $crate::query::arena_cached::ArenaCached;
360                        <Value<'tcx> as ArenaCached>::alloc_in_arena(
361                            tcx,
362                            &tcx.query_system.arenas.$name,
363                            provided_value,
364                        )
365                    };
366
367                    // Otherwise, the provided value is the value (and `tcx` is unused).
368                    #[cfg(not($arena_cache))]
369                    let value: Value<'tcx> = {
370                        let _ = tcx;
371                        provided_value
372                    };
373
374                    erase::erase_val(value)
375                }
376
377                // Ensure that keys grow no larger than 88 bytes by accident.
378                // Increase this limit if necessary, but do try to keep the size low if possible
379                #[cfg(target_pointer_width = "64")]
380                const _: () = {
381                    if size_of::<Key<'static>>() > 88 {
382                        panic!("{}", concat!(
383                            "the query `",
384                            stringify!($name),
385                            "` has a key type `",
386                            stringify!($($K)*),
387                            "` that is too large"
388                        ));
389                    }
390                };
391
392                // Ensure that values grow no larger than 64 bytes by accident.
393                // Increase this limit if necessary, but do try to keep the size low if possible
394                #[cfg(target_pointer_width = "64")]
395                #[cfg(not(feature = "rustc_randomized_layouts"))]
396                const _: () = {
397                    if size_of::<Value<'static>>() > 64 {
398                        panic!("{}", concat!(
399                            "the query `",
400                            stringify!($name),
401                            "` has a value type `",
402                            stringify!($V),
403                            "` that is too large"
404                        ));
405                    }
406                };
407            }
408        )*
409
410        /// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a
411        /// number.
412        #[allow(non_camel_case_types)]
413        #[derive(Clone, Copy, Debug)]
414        pub enum TaggedQueryKey<'tcx> {
415            $(
416                $name($name::Key<'tcx>),
417            )*
418        }
419
420        impl<'tcx> TaggedQueryKey<'tcx> {
421            /// Returns the name of the query this key is tagged with.
422            ///
423            /// This is useful for error/debug output, but don't use it to check for
424            /// specific query names. Instead, match on the `TaggedQueryKey` variant.
425            pub fn query_name(&self) -> &'static str {
426                match self {
427                    $(
428                        TaggedQueryKey::$name(_) => stringify!($name),
429                    )*
430                }
431            }
432
433            /// Formats a human-readable description of this query and its key, as
434            /// specified by the `desc` query modifier.
435            ///
436            /// Used when reporting query cycle errors and similar problems.
437            pub fn description(&self, tcx: TyCtxt<'tcx>) -> String {
438                let (name, description) = ty::print::with_no_queries!(match self {
439                    $(
440                        TaggedQueryKey::$name(key) => (stringify!($name), ($desc)(tcx, *key)),
441                    )*
442                });
443                if tcx.sess.verbose_internals() {
444                    format!("{description} [{name:?}]")
445                } else {
446                    description
447                }
448            }
449
450            /// Returns the default span for this query if `span` is a dummy span.
451            pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
452                if !span.is_dummy() {
453                    return span
454                }
455                if let TaggedQueryKey::def_span(..) = self {
456                    // The `def_span` query is used to calculate `default_span`,
457                    // so exit to avoid infinite recursion.
458                    return DUMMY_SP
459                }
460                match self {
461                    $(
462                        TaggedQueryKey::$name(key) =>
463                            $crate::query::QueryKey::default_span(key, tcx),
464                    )*
465                }
466            }
467        }
468
469        /// Holds a `QueryVTable` for each query.
470        pub struct QueryVTables<'tcx> {
471            $(
472                pub $name: $crate::query::QueryVTable<'tcx, $name::Cache<'tcx>>,
473            )*
474        }
475
476        /// Holds per-query arenas for queries with the `arena_cache` modifier.
477        #[derive(Default)]
478        pub struct QueryArenas<'tcx> {
479            $(
480                // Use the `ArenaCached` helper trait to determine the arena's value type.
481                #[cfg($arena_cache)]
482                pub $name: TypedArena<
483                    <$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
484                >,
485            )*
486        }
487
488        pub struct Providers {
489            $(
490                /// This is the provider for the query. Use `Find references` on this to
491                /// navigate between the provider assignment and the query definition.
492                pub $name: for<'tcx> fn(
493                    TyCtxt<'tcx>,
494                    $name::LocalKey<'tcx>,
495                ) -> $name::ProvidedValue<'tcx>,
496            )*
497        }
498
499        pub struct ExternProviders {
500            $(
501                #[cfg($separate_provide_extern)]
502                pub $name: for<'tcx> fn(
503                    TyCtxt<'tcx>,
504                    $name::Key<'tcx>,
505                ) -> $name::ProvidedValue<'tcx>,
506            )*
507        }
508
509        impl Default for Providers {
510            fn default() -> Self {
511                Providers {
512                    $(
513                        $name: |_, key| {
514                            $crate::query::plumbing::default_query(stringify!($name), &key)
515                        },
516                    )*
517                }
518            }
519        }
520
521        impl Default for ExternProviders {
522            fn default() -> Self {
523                ExternProviders {
524                    $(
525                        #[cfg($separate_provide_extern)]
526                        $name: |_, key| $crate::query::plumbing::default_extern_query(
527                            stringify!($name),
528                            &key,
529                        ),
530                    )*
531                }
532            }
533        }
534
535        impl Copy for Providers {}
536        impl Clone for Providers {
537            fn clone(&self) -> Self { *self }
538        }
539
540        impl Copy for ExternProviders {}
541        impl Clone for ExternProviders {
542            fn clone(&self) -> Self { *self }
543        }
544
545        impl<'tcx> TyCtxt<'tcx> {
546            $(
547                $(#[$attr])*
548                #[inline(always)]
549                #[must_use]
550                pub fn $name(self, key: maybe_into_query_key!($($K)*)) -> $V {
551                    self.at(DUMMY_SP).$name(key)
552                }
553            )*
554        }
555
556        impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
557            $(
558                $(#[$attr])*
559                #[inline(always)]
560                pub fn $name(self, key: maybe_into_query_key!($($K)*)) -> $V {
561                    use $crate::query::{erase, inner};
562
563                    erase::restore_val::<$V>(inner::query_get_at(
564                        self.tcx,
565                        self.span,
566                        &self.tcx.query_system.query_vtables.$name,
567                        $crate::query::IntoQueryKey::into_query_key(key),
568                    ))
569                }
570            )*
571        }
572
573        impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
574            $(
575                $(#[$attr])*
576                #[inline(always)]
577                pub fn $name(self, key: maybe_into_query_key!($($K)*)) {
578                    $crate::query::inner::query_ensure_ok_or_done(
579                        self.tcx,
580                        &self.tcx.query_system.query_vtables.$name,
581                        $crate::query::IntoQueryKey::into_query_key(key),
582                        $crate::query::EnsureMode::Ok,
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                    $crate::query::inner::query_ensure_ok_or_done(
613                        self.tcx,
614                        &self.tcx.query_system.query_vtables.$name,
615                        $crate::query::IntoQueryKey::into_query_key(key),
616                        $crate::query::EnsureMode::Done,
617                    );
618                }
619            )*
620        }
621
622        $(
623            // Only defined when the `feedable` modifier is present.
624            #[cfg($feedable)]
625            impl<'tcx, K: $crate::query::IntoQueryKey<$name::Key<'tcx>> + Copy>
626                TyCtxtFeed<'tcx, K>
627            {
628                $(#[$attr])*
629                #[inline(always)]
630                pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
631                    $crate::query::inner::query_feed(
632                        self.tcx,
633                        &self.tcx.query_system.query_vtables.$name,
634                        self.key().into_query_key(),
635                        $name::provided_to_erased(self.tcx, value),
636                    );
637                }
638            }
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 maybe_into_query_key;
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}