Skip to main content

rustc_middle/query/
plumbing.rs

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