Skip to main content

rustc_middle/query/
plumbing.rs

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