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
65#[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)]
66pub struct CycleError<I = QueryStackFrameExtra> {
67    /// The query and related span that uses the cycle.
68    pub usage: Option<(Span, QueryStackFrame<I>)>,
69    pub cycle: Vec<QueryInfo<I>>,
70}
71
72impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
73    pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
74        CycleError {
75            usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())),
76            cycle: self.cycle.iter().map(|info| info.lift()).collect(),
77        }
78    }
79}
80
81#[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)]
82pub enum QueryMode {
83    /// This is a normal query call to `tcx.$query(..)` or `tcx.at(span).$query(..)`.
84    Get,
85    /// This is a call to `tcx.ensure_ok().$query(..)` or `tcx.ensure_done().$query(..)`.
86    Ensure { ensure_mode: EnsureMode },
87}
88
89/// Distinguishes between `tcx.ensure_ok()` and `tcx.ensure_done()` in shared
90/// code paths that handle both modes.
91#[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)]
92pub enum EnsureMode {
93    /// Corresponds to [`TyCtxt::ensure_ok`].
94    Ok,
95    /// Corresponds to [`TyCtxt::ensure_done`].
96    Done,
97}
98
99/// Stores data and metadata (e.g. function pointers) for a particular query.
100pub struct QueryVTable<'tcx, C: QueryCache> {
101    pub name: &'static str,
102
103    /// True if this query has the `anon` modifier.
104    pub anon: bool,
105    /// True if this query has the `eval_always` modifier.
106    pub eval_always: bool,
107    /// True if this query has the `depth_limit` modifier.
108    pub depth_limit: bool,
109    /// True if this query has the `feedable` modifier.
110    pub feedable: bool,
111
112    pub dep_kind: DepKind,
113    /// How this query deals with query cycle errors.
114    pub cycle_error_handling: CycleErrorHandling,
115    pub state: QueryState<'tcx, C::Key>,
116    pub cache: C,
117    pub will_cache_on_disk_for_key_fn: Option<fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool>,
118
119    /// Function pointer that calls `tcx.$query(key)` for this query and
120    /// discards the returned value.
121    ///
122    /// This is a weird thing to be doing, and probably not what you want.
123    /// It is used for loading query results from disk-cache in some cases.
124    pub call_query_method_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key),
125
126    /// Function pointer that actually calls this query's provider.
127    /// Also performs some associated secondary tasks; see the macro-defined
128    /// implementation in `mod invoke_provider_fn` for more details.
129    ///
130    /// This should be the only code that calls the provider function.
131    pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
132
133    pub try_load_from_disk_fn: Option<
134        fn(
135            tcx: TyCtxt<'tcx>,
136            key: &C::Key,
137            prev_index: SerializedDepNodeIndex,
138            index: DepNodeIndex,
139        ) -> Option<C::Value>,
140    >,
141
142    pub is_loadable_from_disk_fn:
143        Option<fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool>,
144
145    /// Function pointer that hashes this query's result values.
146    ///
147    /// For `no_hash` queries, this function pointer is None.
148    pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
149
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
336macro_rules! define_callbacks {
337    (
338        // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
339        // `query_helper_param_ty!` can match on specific type names.
340        queries {
341            $(
342                $(#[$attr:meta])*
343                fn $name:ident($($K:tt)*) -> $V:ty
344                {
345                    // Search for (QMODLIST) to find all occurrences of this query modifier list.
346                    anon: $anon:literal,
347                    arena_cache: $arena_cache:literal,
348                    cache_on_disk: $cache_on_disk:literal,
349                    cycle_error_handling: $cycle_error_handling:ident,
350                    depth_limit: $depth_limit:literal,
351                    eval_always: $eval_always:literal,
352                    feedable: $feedable:literal,
353                    no_hash: $no_hash:literal,
354                    return_result_from_ensure_ok: $return_result_from_ensure_ok:literal,
355                    separate_provide_extern: $separate_provide_extern:literal,
356                }
357            )*
358        }
359        // Non-queries are unused here.
360        non_queries { $($_:tt)* }
361    ) => {
362        $(
363            #[allow(unused_lifetimes)]
364            pub mod $name {
365                use super::*;
366                use $crate::query::erase::{self, Erased};
367
368                pub type Key<'tcx> = $($K)*;
369                pub type Value<'tcx> = $V;
370
371                /// Key type used by provider functions in `local_providers`.
372                /// This query has the `separate_provide_extern` modifier.
373                #[cfg($separate_provide_extern)]
374                pub type LocalKey<'tcx> =
375                    <Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey;
376                /// Key type used by provider functions in `local_providers`.
377                #[cfg(not($separate_provide_extern))]
378                pub type LocalKey<'tcx> = Key<'tcx>;
379
380                /// Return type of the `.ensure_ok()` method for this query,
381                /// which has the `return_result_from_ensure_ok` modifier.
382                #[cfg($return_result_from_ensure_ok)]
383                pub type EnsureOkReturnType = Result<(), rustc_errors::ErrorGuaranteed>;
384                /// Return type of the `.ensure_ok()` method for this query,
385                /// which does _not_ have the `return_result_from_ensure_ok` modifier.
386                #[cfg(not($return_result_from_ensure_ok))]
387                pub type EnsureOkReturnType = ();
388
389                /// Type returned from query providers and loaded from disk-cache.
390                #[cfg($arena_cache)]
391                pub type ProvidedValue<'tcx> =
392                    <Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided;
393                /// Type returned from query providers and loaded from disk-cache.
394                #[cfg(not($arena_cache))]
395                pub type ProvidedValue<'tcx> = Value<'tcx>;
396
397                /// This helper function takes a value returned by the query provider
398                /// (or loaded from disk, or supplied by query feeding), allocates
399                /// it in an arena if requested by the `arena_cache` modifier, and
400                /// then returns an erased copy of it.
401                #[inline(always)]
402                pub fn provided_to_erased<'tcx>(
403                    tcx: TyCtxt<'tcx>,
404                    provided_value: ProvidedValue<'tcx>,
405                ) -> Erased<Value<'tcx>> {
406                    // For queries with the `arena_cache` modifier, store the
407                    // provided value in an arena and get a reference to it.
408                    #[cfg($arena_cache)]
409                    let value: Value<'tcx> = {
410                        use $crate::query::arena_cached::ArenaCached;
411                        <Value<'tcx> as ArenaCached>::alloc_in_arena(
412                            tcx,
413                            &tcx.query_system.arenas.$name,
414                            provided_value,
415                        )
416                    };
417
418                    // Otherwise, the provided value is the value (and `tcx` is unused).
419                    #[cfg(not($arena_cache))]
420                    let value: Value<'tcx> = {
421                        let _ = tcx;
422                        provided_value
423                    };
424
425                    erase::erase_val(value)
426                }
427
428                pub type Cache<'tcx> =
429                    <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
430
431                // Ensure that keys grow no larger than 88 bytes by accident.
432                // Increase this limit if necessary, but do try to keep the size low if possible
433                #[cfg(target_pointer_width = "64")]
434                const _: () = {
435                    if size_of::<Key<'static>>() > 88 {
436                        panic!("{}", concat!(
437                            "the query `",
438                            stringify!($name),
439                            "` has a key type `",
440                            stringify!($($K)*),
441                            "` that is too large"
442                        ));
443                    }
444                };
445
446                // Ensure that values grow no larger than 64 bytes by accident.
447                // Increase this limit if necessary, but do try to keep the size low if possible
448                #[cfg(target_pointer_width = "64")]
449                #[cfg(not(feature = "rustc_randomized_layouts"))]
450                const _: () = {
451                    if size_of::<Value<'static>>() > 64 {
452                        panic!("{}", concat!(
453                            "the query `",
454                            stringify!($name),
455                            "` has a value type `",
456                            stringify!($V),
457                            "` that is too large"
458                        ));
459                    }
460                };
461            }
462        )*
463
464        /// Holds per-query arenas for queries with the `arena_cache` modifier.
465        #[derive(Default)]
466        pub struct QueryArenas<'tcx> {
467            $(
468                // Use the `ArenaCached` helper trait to determine the arena's value type.
469                #[cfg($arena_cache)]
470                pub $name: TypedArena<
471                    <$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
472                >,
473            )*
474        }
475
476        impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
477            $(
478                $(#[$attr])*
479                #[inline(always)]
480                pub fn $name(
481                    self,
482                    key: query_helper_param_ty!($($K)*),
483                ) -> $crate::queries::$name::EnsureOkReturnType {
484
485                    #[cfg($return_result_from_ensure_ok)]
486                    let ensure_fn = crate::query::inner::query_ensure_error_guaranteed;
487                    #[cfg(not($return_result_from_ensure_ok))]
488                    let ensure_fn = crate::query::inner::query_ensure;
489
490                    ensure_fn(
491                        self.tcx,
492                        &self.tcx.query_system.query_vtables.$name,
493                        $crate::query::IntoQueryParam::into_query_param(key),
494                        $crate::query::EnsureMode::Ok,
495                    )
496                }
497            )*
498        }
499
500        impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
501            $(
502                $(#[$attr])*
503                #[inline(always)]
504                pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
505                    crate::query::inner::query_ensure(
506                        self.tcx,
507                        &self.tcx.query_system.query_vtables.$name,
508                        $crate::query::IntoQueryParam::into_query_param(key),
509                        $crate::query::EnsureMode::Done,
510                    );
511                }
512            )*
513        }
514
515        impl<'tcx> TyCtxt<'tcx> {
516            $(
517                $(#[$attr])*
518                #[inline(always)]
519                #[must_use]
520                pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
521                    self.at(DUMMY_SP).$name(key)
522                }
523            )*
524        }
525
526        impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
527            $(
528                $(#[$attr])*
529                #[inline(always)]
530                pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
531                    use $crate::query::{erase, inner};
532
533                    erase::restore_val::<$V>(inner::query_get_at(
534                        self.tcx,
535                        self.span,
536                        &self.tcx.query_system.query_vtables.$name,
537                        $crate::query::IntoQueryParam::into_query_param(key),
538                    ))
539                }
540            )*
541        }
542
543        $(
544            #[cfg($feedable)]
545            impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy>
546                TyCtxtFeed<'tcx, K>
547            {
548                $(#[$attr])*
549                #[inline(always)]
550                pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
551                    let key = self.key().into_query_param();
552                    let erased_value = $name::provided_to_erased(self.tcx, value);
553                    $crate::query::inner::query_feed(
554                        self.tcx,
555                        dep_graph::DepKind::$name,
556                        &self.tcx.query_system.query_vtables.$name,
557                        key,
558                        erased_value,
559                    );
560                }
561            }
562        )*
563
564        /// Holds a `QueryVTable` for each query.
565        pub struct QueryVTables<'tcx> {
566            $(
567                pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Cache<'tcx>>,
568            )*
569        }
570
571        pub struct Providers {
572            $(
573                /// This is the provider for the query. Use `Find references` on this to
574                /// navigate between the provider assignment and the query definition.
575                pub $name: for<'tcx> fn(
576                    TyCtxt<'tcx>,
577                    $name::LocalKey<'tcx>,
578                ) -> $name::ProvidedValue<'tcx>,
579            )*
580        }
581
582        pub struct ExternProviders {
583            $(
584                #[cfg($separate_provide_extern)]
585                pub $name: for<'tcx> fn(
586                    TyCtxt<'tcx>,
587                    $name::Key<'tcx>,
588                ) -> $name::ProvidedValue<'tcx>,
589            )*
590        }
591
592        impl Default for Providers {
593            fn default() -> Self {
594                Providers {
595                    $(
596                        $name: |_, key| {
597                            $crate::query::plumbing::default_query(stringify!($name), &key)
598                        },
599                    )*
600                }
601            }
602        }
603
604        impl Default for ExternProviders {
605            fn default() -> Self {
606                ExternProviders {
607                    $(
608                        #[cfg($separate_provide_extern)]
609                        $name: |_, key| $crate::query::plumbing::default_extern_query(
610                            stringify!($name),
611                            &key,
612                        ),
613                    )*
614                }
615            }
616        }
617
618        impl Copy for Providers {}
619        impl Clone for Providers {
620            fn clone(&self) -> Self { *self }
621        }
622
623        impl Copy for ExternProviders {}
624        impl Clone for ExternProviders {
625            fn clone(&self) -> Self { *self }
626        }
627    };
628}
629
630mod sealed {
631    use rustc_hir::def_id::{LocalModDefId, ModDefId};
632
633    use super::{DefId, LocalDefId, OwnerId};
634
635    /// An analogue of the `Into` trait that's intended only for query parameters.
636    ///
637    /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
638    /// user call `to_def_id` to convert between them everywhere else.
639    pub trait IntoQueryParam<P> {
640        fn into_query_param(self) -> P;
641    }
642
643    impl<P> IntoQueryParam<P> for P {
644        #[inline(always)]
645        fn into_query_param(self) -> P {
646            self
647        }
648    }
649
650    impl IntoQueryParam<LocalDefId> for OwnerId {
651        #[inline(always)]
652        fn into_query_param(self) -> LocalDefId {
653            self.def_id
654        }
655    }
656
657    impl IntoQueryParam<DefId> for LocalDefId {
658        #[inline(always)]
659        fn into_query_param(self) -> DefId {
660            self.to_def_id()
661        }
662    }
663
664    impl IntoQueryParam<DefId> for OwnerId {
665        #[inline(always)]
666        fn into_query_param(self) -> DefId {
667            self.to_def_id()
668        }
669    }
670
671    impl IntoQueryParam<DefId> for ModDefId {
672        #[inline(always)]
673        fn into_query_param(self) -> DefId {
674            self.to_def_id()
675        }
676    }
677
678    impl IntoQueryParam<DefId> for LocalModDefId {
679        #[inline(always)]
680        fn into_query_param(self) -> DefId {
681            self.to_def_id()
682        }
683    }
684
685    impl IntoQueryParam<LocalDefId> for LocalModDefId {
686        #[inline(always)]
687        fn into_query_param(self) -> LocalDefId {
688            self.into()
689        }
690    }
691}
692
693#[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)]
694pub struct CyclePlaceholder(pub ErrorGuaranteed);
695
696#[cold]
697pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
698    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!(
699        "`tcx.{name}({key:?})` is not supported for this key;\n\
700        hint: Queries can be either made to the local crate, or the external crate. \
701        This error means you tried to use it for one that's not supported.\n\
702        If that's not the case, {name} was likely never assigned to a provider function.\n",
703    )
704}
705
706#[cold]
707pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
708    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!(
709        "`tcx.{name}({key:?})` unsupported by its crate; \
710         perhaps the `{name}` query was never assigned a provider function",
711    )
712}