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