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_hir::def_id::{DefId, LocalDefId};
9use rustc_hir::hir_id::OwnerId;
10use rustc_macros::HashStable;
11use rustc_span::{ErrorGuaranteed, Span};
12pub use sealed::IntoQueryParam;
13
14use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
15use crate::ich::StableHashingContext;
16use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables};
17use crate::query::on_disk_cache::OnDiskCache;
18use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
19use crate::query::{QueryCache, QueryInfo, QueryJob};
20use crate::ty::TyCtxt;
21
22/// For a particular query, keeps track of "active" keys, i.e. keys whose
23/// evaluation has started but has not yet finished successfully.
24///
25/// (Successful query evaluation for a key is represented by an entry in the
26/// query's in-memory cache.)
27pub struct QueryState<'tcx, K> {
28    pub active: Sharded<HashTable<(K, ActiveKeyStatus<'tcx>)>>,
29}
30
31impl<'tcx, K> Default for QueryState<'tcx, K> {
32    fn default() -> QueryState<'tcx, K> {
33        QueryState { active: Default::default() }
34    }
35}
36
37/// For a particular query and key, tracks the status of a query evaluation
38/// that has started, but has not yet finished successfully.
39///
40/// (Successful query evaluation for a key is represented by an entry in the
41/// query's in-memory cache.)
42pub enum ActiveKeyStatus<'tcx> {
43    /// Some thread is already evaluating the query for this key.
44    ///
45    /// The enclosed [`QueryJob`] can be used to wait for it to finish.
46    Started(QueryJob<'tcx>),
47
48    /// The query panicked. Queries trying to wait on this will raise a fatal error which will
49    /// silently panic.
50    Poisoned,
51}
52
53/// How a particular query deals with query cycle errors.
54///
55/// Inspected by the code that actually handles cycle errors, to decide what
56/// approach to use.
57#[derive(#[automatically_derived]
impl ::core::marker::Copy for CycleErrorHandling { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CycleErrorHandling {
    #[inline]
    fn clone(&self) -> CycleErrorHandling { *self }
}Clone)]
58pub enum CycleErrorHandling {
59    Error,
60    Fatal,
61    DelayBug,
62    Stash,
63}
64
65pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool;
66
67pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn(
68    tcx: TyCtxt<'tcx>,
69    key: &Key,
70    prev_index: SerializedDepNodeIndex,
71    index: DepNodeIndex,
72) -> Option<Value>;
73
74pub type IsLoadableFromDiskFn<'tcx, Key> =
75    fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool;
76
77pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
78
79#[derive(#[automatically_derived]
impl<I: ::core::clone::Clone> ::core::clone::Clone for CycleError<I> {
    #[inline]
    fn clone(&self) -> CycleError<I> {
        CycleError {
            usage: ::core::clone::Clone::clone(&self.usage),
            cycle: ::core::clone::Clone::clone(&self.cycle),
        }
    }
}Clone, #[automatically_derived]
impl<I: ::core::fmt::Debug> ::core::fmt::Debug for CycleError<I> {
    #[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)]
80pub struct CycleError<I = QueryStackFrameExtra> {
81    /// The query and related span that uses the cycle.
82    pub usage: Option<(Span, QueryStackFrame<I>)>,
83    pub cycle: Vec<QueryInfo<I>>,
84}
85
86impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
87    pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
88        CycleError {
89            usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())),
90            cycle: self.cycle.iter().map(|info| info.lift()).collect(),
91        }
92    }
93}
94
95#[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)]
96pub enum QueryMode {
97    /// This is a normal query call to `tcx.$query(..)` or `tcx.at(span).$query(..)`.
98    Get,
99    /// This is a call to `tcx.ensure_ok().$query(..)` or `tcx.ensure_done().$query(..)`.
100    Ensure { ensure_mode: EnsureMode },
101}
102
103/// Distinguishes between `tcx.ensure_ok()` and `tcx.ensure_done()` in shared
104/// code paths that handle both modes.
105#[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)]
106pub enum EnsureMode {
107    /// Corresponds to [`TyCtxt::ensure_ok`].
108    Ok,
109    /// Corresponds to [`TyCtxt::ensure_done`].
110    Done,
111}
112
113/// Stores data and metadata (e.g. function pointers) for a particular query.
114pub struct QueryVTable<'tcx, C: QueryCache> {
115    pub name: &'static str,
116
117    /// True if this query has the `anon` modifier.
118    pub anon: bool,
119    /// True if this query has the `eval_always` modifier.
120    pub eval_always: bool,
121    /// True if this query has the `depth_limit` modifier.
122    pub depth_limit: bool,
123    /// True if this query has the `feedable` modifier.
124    pub feedable: bool,
125
126    pub dep_kind: DepKind,
127    /// How this query deals with query cycle errors.
128    pub cycle_error_handling: CycleErrorHandling,
129    pub state: QueryState<'tcx, C::Key>,
130    pub cache: C,
131    pub will_cache_on_disk_for_key_fn: Option<WillCacheOnDiskForKeyFn<'tcx, C::Key>>,
132
133    /// Function pointer that calls `tcx.$query(key)` for this query and
134    /// discards the returned value.
135    ///
136    /// This is a weird thing to be doing, and probably not what you want.
137    /// It is used for loading query results from disk-cache in some cases.
138    pub call_query_method_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key),
139
140    /// Function pointer that actually calls this query's provider.
141    /// Also performs some associated secondary tasks; see the macro-defined
142    /// implementation in `mod invoke_provider_fn` for more details.
143    ///
144    /// This should be the only code that calls the provider function.
145    pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
146
147    pub try_load_from_disk_fn: Option<TryLoadFromDiskFn<'tcx, C::Key, C::Value>>,
148    pub is_loadable_from_disk_fn: Option<IsLoadableFromDiskFn<'tcx, C::Key>>,
149    pub hash_result: HashResult<C::Value>,
150    pub value_from_cycle_error:
151        fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value,
152    pub format_value: fn(&C::Value) -> String,
153
154    /// Formats a human-readable description of this query and its key, as
155    /// specified by the `desc` query modifier.
156    ///
157    /// Used when reporting query cycle errors and similar problems.
158    pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String,
159
160    /// Function pointer that is called by the query methods on [`TyCtxt`] and
161    /// friends[^1], after they have checked the in-memory cache and found no
162    /// existing value for this key.
163    ///
164    /// Transitive responsibilities include trying to load a disk-cached value
165    /// if possible (incremental only), invoking the query provider if necessary,
166    /// and putting the obtained value into the in-memory cache.
167    ///
168    /// [^1]: [`TyCtxt`], [`TyCtxtAt`], [`TyCtxtEnsureOk`], [`TyCtxtEnsureDone`]
169    pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
170}
171
172impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        // When debug-printing a query vtable (e.g. for ICE or tracing),
175        // just print the query name to know what query we're dealing with.
176        // The other fields and flags are probably just unhelpful noise.
177        //
178        // If there is need for a more detailed dump of all flags and fields,
179        // consider writing a separate dump method and calling it explicitly.
180        f.write_str(self.name)
181    }
182}
183
184impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> {
185    #[inline(always)]
186    pub fn will_cache_on_disk_for_key(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool {
187        self.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key))
188    }
189
190    #[inline(always)]
191    pub fn try_load_from_disk(
192        &self,
193        tcx: TyCtxt<'tcx>,
194        key: &C::Key,
195        prev_index: SerializedDepNodeIndex,
196        index: DepNodeIndex,
197    ) -> Option<C::Value> {
198        // `?` will return None immediately for queries that never cache to disk.
199        self.try_load_from_disk_fn?(tcx, key, prev_index, index)
200    }
201
202    #[inline]
203    pub fn is_loadable_from_disk(
204        &self,
205        tcx: TyCtxt<'tcx>,
206        key: &C::Key,
207        index: SerializedDepNodeIndex,
208    ) -> bool {
209        self.is_loadable_from_disk_fn.map_or(false, |f| f(tcx, key, index))
210    }
211
212    /// Synthesize an error value to let compilation continue after a cycle.
213    pub fn value_from_cycle_error(
214        &self,
215        tcx: TyCtxt<'tcx>,
216        cycle_error: &CycleError,
217        guar: ErrorGuaranteed,
218    ) -> C::Value {
219        (self.value_from_cycle_error)(tcx, cycle_error, guar)
220    }
221
222    pub fn construct_dep_node(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> DepNode {
223        DepNode::construct(tcx, self.dep_kind, key)
224    }
225}
226
227pub struct QuerySystem<'tcx> {
228    pub arenas: WorkerLocal<QueryArenas<'tcx>>,
229    pub query_vtables: QueryVTables<'tcx>,
230
231    /// This provides access to the incremental compilation on-disk cache for query results.
232    /// Do not access this directly. It is only meant to be used by
233    /// `DepGraph::try_mark_green()` and the query infrastructure.
234    /// This is `None` if we are not incremental compilation mode
235    pub on_disk_cache: Option<OnDiskCache>,
236
237    pub local_providers: Providers,
238    pub extern_providers: ExternProviders,
239
240    pub jobs: AtomicU64,
241}
242
243#[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)]
244pub struct TyCtxtAt<'tcx> {
245    pub tcx: TyCtxt<'tcx>,
246    pub span: Span,
247}
248
249impl<'tcx> Deref for TyCtxtAt<'tcx> {
250    type Target = TyCtxt<'tcx>;
251    #[inline(always)]
252    fn deref(&self) -> &Self::Target {
253        &self.tcx
254    }
255}
256
257#[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)]
258#[must_use]
259pub struct TyCtxtEnsureOk<'tcx> {
260    pub tcx: TyCtxt<'tcx>,
261}
262
263#[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)]
264#[must_use]
265pub struct TyCtxtEnsureDone<'tcx> {
266    pub tcx: TyCtxt<'tcx>,
267}
268
269impl<'tcx> TyCtxt<'tcx> {
270    /// Wrapper that calls queries in a special "ensure OK" mode, for callers
271    /// that don't need the return value and just want to invoke a query for
272    /// its potential side-effect of emitting fatal errors.
273    ///
274    /// This can be more efficient than a normal query call, because if the
275    /// query's inputs are all green, the call can return immediately without
276    /// needing to obtain a value (by decoding one from disk or by executing
277    /// the query).
278    ///
279    /// (As with all query calls, execution is also skipped if the query result
280    /// is already cached in memory.)
281    ///
282    /// ## WARNING
283    /// A subsequent normal call to the same query might still cause it to be
284    /// executed! This can occur when the inputs are all green, but the query's
285    /// result is not cached on disk, so the query must be executed to obtain a
286    /// return value.
287    ///
288    /// Therefore, this call mode is not appropriate for callers that want to
289    /// ensure that the query is _never_ executed in the future.
290    ///
291    /// ## `return_result_from_ensure_ok`
292    /// If a query has the `return_result_from_ensure_ok` modifier, calls via
293    /// `ensure_ok` will instead return `Result<(), ErrorGuaranteed>`. If the
294    /// query needs to be executed, and execution returns an error, that error
295    /// is returned to the caller.
296    #[inline(always)]
297    pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> {
298        TyCtxtEnsureOk { tcx: self }
299    }
300
301    /// Wrapper that calls queries in a special "ensure done" mode, for callers
302    /// that don't need the return value and just want to guarantee that the
303    /// query won't be executed in the future, by executing it now if necessary.
304    ///
305    /// This is useful for queries that read from a [`Steal`] value, to ensure
306    /// that they are executed before the query that will steal the value.
307    ///
308    /// Unlike [`Self::ensure_ok`], a query with all-green inputs will only be
309    /// skipped if its return value is stored in the disk-cache. This is still
310    /// more efficient than a regular query, because in that situation the
311    /// return value doesn't necessarily need to be decoded.
312    ///
313    /// (As with all query calls, execution is also skipped if the query result
314    /// is already cached in memory.)
315    ///
316    /// [`Steal`]: rustc_data_structures::steal::Steal
317    #[inline(always)]
318    pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> {
319        TyCtxtEnsureDone { tcx: self }
320    }
321
322    /// Returns a transparent wrapper for `TyCtxt` which uses
323    /// `span` as the location of queries performed through it.
324    #[inline(always)]
325    pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
326        TyCtxtAt { tcx: self, span }
327    }
328}
329
330macro_rules! query_helper_param_ty {
331    (DefId) => { impl $crate::query::IntoQueryParam<DefId> };
332    (LocalDefId) => { impl $crate::query::IntoQueryParam<LocalDefId> };
333    ($K:ty) => { $K };
334}
335
336// Expands to `$yes` if the `arena_cache` modifier is present, `$no` otherwise.
337macro_rules! if_arena_cache {
338    ([] $then:tt $no:tt) => { $no };
339    ([(arena_cache) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
340    ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
341        if_arena_cache!([$($modifiers)*] $yes $no)
342    };
343}
344
345// Expands to `$yes` if the `separate_provide_extern` modifier is present, `$no` otherwise.
346macro_rules! if_separate_provide_extern {
347    ([] $then:tt $no:tt) => { $no };
348    ([(separate_provide_extern) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
349    ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
350        if_separate_provide_extern!([$($modifiers)*] $yes $no)
351    };
352}
353
354// Expands to `$yes` if the `return_result_from_ensure_ok` modifier is present, `$no` otherwise.
355macro_rules! if_return_result_from_ensure_ok {
356    ([] $then:tt $no:tt) => { $no };
357    ([(return_result_from_ensure_ok) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
358    ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
359        if_return_result_from_ensure_ok!([$($modifiers)*] $yes $no)
360    };
361}
362
363// Expands to `$item` if the `feedable` modifier is present.
364macro_rules! item_if_feedable {
365    ([] $($item:tt)*) => {};
366    ([(feedable) $($rest:tt)*] $($item:tt)*) => {
367        $($item)*
368    };
369    ([$other:tt $($modifiers:tt)*] $($item:tt)*) => {
370        item_if_feedable! { [$($modifiers)*] $($item)* }
371    };
372}
373
374macro_rules! define_callbacks {
375    (
376        // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
377        // `query_helper_param_ty!` can match on specific type names.
378        $(
379            $(#[$attr:meta])*
380            [$($modifiers:tt)*]
381            fn $name:ident($($K:tt)*) -> $V:ty,
382        )*
383    ) => {
384        $(
385            #[allow(unused_lifetimes)]
386            pub mod $name {
387                use super::*;
388                use $crate::query::erase::{self, Erased};
389
390                pub type Key<'tcx> = $($K)*;
391                pub type Value<'tcx> = $V;
392
393                pub type LocalKey<'tcx> = if_separate_provide_extern!(
394                    [$($modifiers)*]
395                    (<Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey)
396                    (Key<'tcx>)
397                );
398
399                /// This type alias specifies the type returned from query providers and the type
400                /// used for decoding. For regular queries this is the declared returned type `V`,
401                /// but `arena_cache` will use `<V as ArenaCached>::Provided` instead.
402                pub type ProvidedValue<'tcx> = if_arena_cache!(
403                    [$($modifiers)*]
404                    (<Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided)
405                    (Value<'tcx>)
406                );
407
408                /// This helper function takes a value returned by the query provider
409                /// (or loaded from disk, or supplied by query feeding), allocates
410                /// it in an arena if requested by the `arena_cache` modifier, and
411                /// then returns an erased copy of it.
412                #[inline(always)]
413                pub fn provided_to_erased<'tcx>(
414                    tcx: TyCtxt<'tcx>,
415                    provided_value: ProvidedValue<'tcx>,
416                ) -> Erased<Value<'tcx>> {
417                    // For queries with the `arena_cache` modifier, store the
418                    // provided value in an arena and get a reference to it.
419                    let value: Value<'tcx> = if_arena_cache!(
420                        [$($modifiers)*]
421                        {
422                            <Value<'tcx> as $crate::query::arena_cached::ArenaCached>::
423                                alloc_in_arena
424                            (
425                                tcx,
426                                &tcx.query_system.arenas.$name,
427                                provided_value,
428                            )
429                        }
430                        {
431                            // Otherwise, the provided value is the value (and `tcx` is unused).
432                            let _ = tcx;
433                            provided_value
434                        }
435                    );
436                    erase::erase_val(value)
437                }
438
439                pub type Cache<'tcx> =
440                    <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
441
442                // Ensure that keys grow no larger than 88 bytes by accident.
443                // Increase this limit if necessary, but do try to keep the size low if possible
444                #[cfg(target_pointer_width = "64")]
445                const _: () = {
446                    if size_of::<Key<'static>>() > 88 {
447                        panic!("{}", concat!(
448                            "the query `",
449                            stringify!($name),
450                            "` has a key type `",
451                            stringify!($($K)*),
452                            "` that is too large"
453                        ));
454                    }
455                };
456
457                // Ensure that values grow no larger than 64 bytes by accident.
458                // Increase this limit if necessary, but do try to keep the size low if possible
459                #[cfg(target_pointer_width = "64")]
460                #[cfg(not(feature = "rustc_randomized_layouts"))]
461                const _: () = {
462                    if size_of::<Value<'static>>() > 64 {
463                        panic!("{}", concat!(
464                            "the query `",
465                            stringify!($name),
466                            "` has a value type `",
467                            stringify!($V),
468                            "` that is too large"
469                        ));
470                    }
471                };
472            }
473        )*
474
475        /// Holds per-query arenas for queries with the `arena_cache` modifier.
476        #[derive(Default)]
477        pub struct QueryArenas<'tcx> {
478            $(
479                pub $name: if_arena_cache!(
480                    [$($modifiers)*]
481                    // Use the `ArenaCached` helper trait to determine the arena's value type.
482                    (TypedArena<<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated>)
483                    // No arena for this query, so the field type is `()`.
484                    ()
485                ),
486            )*
487        }
488
489        impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
490            $(
491                $(#[$attr])*
492                #[inline(always)]
493                pub fn $name(
494                    self,
495                    key: query_helper_param_ty!($($K)*),
496                ) -> if_return_result_from_ensure_ok!(
497                    [$($modifiers)*]
498                    (Result<(), ErrorGuaranteed>)
499                    ()
500                ) {
501                    if_return_result_from_ensure_ok!(
502                        [$($modifiers)*]
503                        (crate::query::inner::query_ensure_error_guaranteed)
504                        (crate::query::inner::query_ensure)
505                    )(
506                        self.tcx,
507                        &self.tcx.query_system.query_vtables.$name,
508                        $crate::query::IntoQueryParam::into_query_param(key),
509                        $crate::query::EnsureMode::Ok,
510                    )
511                }
512            )*
513        }
514
515        impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
516            $(
517                $(#[$attr])*
518                #[inline(always)]
519                pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
520                    crate::query::inner::query_ensure(
521                        self.tcx,
522                        &self.tcx.query_system.query_vtables.$name,
523                        $crate::query::IntoQueryParam::into_query_param(key),
524                        $crate::query::EnsureMode::Done,
525                    );
526                }
527            )*
528        }
529
530        impl<'tcx> TyCtxt<'tcx> {
531            $(
532                $(#[$attr])*
533                #[inline(always)]
534                #[must_use]
535                pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
536                    self.at(DUMMY_SP).$name(key)
537                }
538            )*
539        }
540
541        impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
542            $(
543                $(#[$attr])*
544                #[inline(always)]
545                pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
546                    use $crate::query::{erase, inner};
547
548                    erase::restore_val::<$V>(inner::query_get_at(
549                        self.tcx,
550                        self.span,
551                        &self.tcx.query_system.query_vtables.$name,
552                        $crate::query::IntoQueryParam::into_query_param(key),
553                    ))
554                }
555            )*
556        }
557
558        $(
559            item_if_feedable! {
560                [$($modifiers)*]
561                impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy>
562                    TyCtxtFeed<'tcx, K>
563                {
564                    $(#[$attr])*
565                    #[inline(always)]
566                    pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
567                        let key = self.key().into_query_param();
568                        let erased_value = $name::provided_to_erased(self.tcx, value);
569                        $crate::query::inner::query_feed(
570                            self.tcx,
571                            dep_graph::DepKind::$name,
572                            &self.tcx.query_system.query_vtables.$name,
573                            key,
574                            erased_value,
575                        );
576                    }
577                }
578            }
579        )*
580
581        /// Holds a `QueryVTable` for each query.
582        pub struct QueryVTables<'tcx> {
583            $(
584                pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Cache<'tcx>>,
585            )*
586        }
587
588        pub struct Providers {
589            $(
590                /// This is the provider for the query. Use `Find references` on this to
591                /// navigate between the provider assignment and the query definition.
592                pub $name: for<'tcx> fn(
593                    TyCtxt<'tcx>,
594                    $name::LocalKey<'tcx>,
595                ) -> $name::ProvidedValue<'tcx>,
596            )*
597        }
598
599        pub struct ExternProviders {
600            $(
601                pub $name: if_separate_provide_extern!(
602                    [$($modifiers)*]
603                    (for<'tcx> fn(TyCtxt<'tcx>, $name::Key<'tcx>) -> $name::ProvidedValue<'tcx>)
604                    ()
605                ),
606            )*
607        }
608
609        impl Default for Providers {
610            fn default() -> Self {
611                Providers {
612                    $(
613                        $name: |_, key| {
614                            $crate::query::plumbing::default_query(stringify!($name), &key)
615                        },
616                    )*
617                }
618            }
619        }
620
621        impl Default for ExternProviders {
622            fn default() -> Self {
623                ExternProviders {
624                    $(
625                        $name: if_separate_provide_extern!(
626                            [$($modifiers)*]
627                            (|_, key| $crate::query::plumbing::default_extern_query(
628                                stringify!($name),
629                                &key
630                            ))
631                            ()
632                        ),
633                    )*
634                }
635            }
636        }
637
638        impl Copy for Providers {}
639        impl Clone for Providers {
640            fn clone(&self) -> Self { *self }
641        }
642
643        impl Copy for ExternProviders {}
644        impl Clone for ExternProviders {
645            fn clone(&self) -> Self { *self }
646        }
647    };
648}
649
650// Each of these queries corresponds to a function pointer field in the
651// `Providers` struct for requesting a value of that type, and a method
652// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
653// which memoizes and does dep-graph tracking, wrapping around the actual
654// `Providers` that the driver creates (using several `rustc_*` crates).
655//
656// The result type of each query must implement `Clone`, and additionally
657// `ty::query::values::Value`, which produces an appropriate placeholder
658// (error) value if the query resulted in a query cycle.
659// Queries marked with `cycle_fatal` do not need the latter implementation,
660// as they will raise an fatal error on query cycles instead.
661
662mod sealed {
663    use rustc_hir::def_id::{LocalModDefId, ModDefId};
664
665    use super::{DefId, LocalDefId, OwnerId};
666
667    /// An analogue of the `Into` trait that's intended only for query parameters.
668    ///
669    /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
670    /// user call `to_def_id` to convert between them everywhere else.
671    pub trait IntoQueryParam<P> {
672        fn into_query_param(self) -> P;
673    }
674
675    impl<P> IntoQueryParam<P> for P {
676        #[inline(always)]
677        fn into_query_param(self) -> P {
678            self
679        }
680    }
681
682    impl IntoQueryParam<LocalDefId> for OwnerId {
683        #[inline(always)]
684        fn into_query_param(self) -> LocalDefId {
685            self.def_id
686        }
687    }
688
689    impl IntoQueryParam<DefId> for LocalDefId {
690        #[inline(always)]
691        fn into_query_param(self) -> DefId {
692            self.to_def_id()
693        }
694    }
695
696    impl IntoQueryParam<DefId> for OwnerId {
697        #[inline(always)]
698        fn into_query_param(self) -> DefId {
699            self.to_def_id()
700        }
701    }
702
703    impl IntoQueryParam<DefId> for ModDefId {
704        #[inline(always)]
705        fn into_query_param(self) -> DefId {
706            self.to_def_id()
707        }
708    }
709
710    impl IntoQueryParam<DefId> for LocalModDefId {
711        #[inline(always)]
712        fn into_query_param(self) -> DefId {
713            self.to_def_id()
714        }
715    }
716
717    impl IntoQueryParam<LocalDefId> for LocalModDefId {
718        #[inline(always)]
719        fn into_query_param(self) -> LocalDefId {
720            self.into()
721        }
722    }
723}
724
725#[derive(#[automatically_derived]
impl ::core::marker::Copy for CyclePlaceholder { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CyclePlaceholder {
    #[inline]
    fn clone(&self) -> CyclePlaceholder {
        let _: ::core::clone::AssertParamIsClone<ErrorGuaranteed>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CyclePlaceholder {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "CyclePlaceholder", &&self.0)
    }
}Debug, const _: () =
    {
        impl<'__ctx>
            ::rustc_data_structures::stable_hasher::HashStable<::rustc_middle::ich::StableHashingContext<'__ctx>>
            for CyclePlaceholder {
            #[inline]
            fn hash_stable(&self,
                __hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    CyclePlaceholder(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable)]
726pub struct CyclePlaceholder(pub ErrorGuaranteed);
727
728#[cold]
729pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
730    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!(
731        "`tcx.{name}({key:?})` is not supported for this key;\n\
732        hint: Queries can be either made to the local crate, or the external crate. \
733        This error means you tried to use it for one that's not supported.\n\
734        If that's not the case, {name} was likely never assigned to a provider function.\n",
735    )
736}
737
738#[cold]
739pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
740    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!(
741        "`tcx.{name}({key:?})` unsupported by its crate; \
742         perhaps the `{name}` query was never assigned a provider function",
743    )
744}