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