1use std::fmt;
2use std::ops::Deref;
34use 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;
1314use 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;
2122/// 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> {
28pub active: Sharded<HashTable<(K, ActiveKeyStatus<'tcx>)>>,
29}
3031impl<'tcx, K> Defaultfor QueryState<'tcx, K> {
32fn default() -> QueryState<'tcx, K> {
33QueryState { active: Default::default() }
34 }
35}
3637/// 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.
46Started(QueryJob<'tcx>),
4748/// The query panicked. Queries trying to wait on this will raise a fatal error which will
49 /// silently panic.
50Poisoned,
51}
5253/// 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}
6465#[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.
68pub usage: Option<(Span, QueryStackFrame<I>)>,
69pub cycle: Vec<QueryInfo<I>>,
70}
7172impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
73pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
74CycleError {
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}
8081#[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(..)`.
84Get,
85/// This is a call to `tcx.ensure_ok().$query(..)` or `tcx.ensure_done().$query(..)`.
86Ensure { ensure_mode: EnsureMode },
87}
8889/// 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`].
94Ok,
95/// Corresponds to [`TyCtxt::ensure_done`].
96Done,
97}
9899/// Stores data and metadata (e.g. function pointers) for a particular query.
100pub struct QueryVTable<'tcx, C: QueryCache> {
101pub name: &'static str,
102103/// True if this query has the `anon` modifier.
104pub anon: bool,
105/// True if this query has the `eval_always` modifier.
106pub eval_always: bool,
107/// True if this query has the `depth_limit` modifier.
108pub depth_limit: bool,
109/// True if this query has the `feedable` modifier.
110pub feedable: bool,
111112pub dep_kind: DepKind,
113/// How this query deals with query cycle errors.
114pub cycle_error_handling: CycleErrorHandling,
115pub state: QueryState<'tcx, C::Key>,
116pub cache: C,
117pub will_cache_on_disk_for_key_fn: Option<fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool>,
118119/// 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.
124pub call_query_method_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key),
125126/// 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.
131pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
132133pub try_load_from_disk_fn: Option<
134fn(
135 tcx: TyCtxt<'tcx>,
136 key: &C::Key,
137 prev_index: SerializedDepNodeIndex,
138 index: DepNodeIndex,
139 ) -> Option<C::Value>,
140 >,
141142pub is_loadable_from_disk_fn:
143Option<fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool>,
144145/// Function pointer that hashes this query's result values.
146 ///
147 /// For `no_hash` queries, this function pointer is None.
148pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
149150pub value_from_cycle_error:
151fn(tcx: TyCtxt<'tcx>, cycle_error: CycleError, guar: ErrorGuaranteed) -> C::Value,
152pub format_value: fn(&C::Value) -> String,
153154/// 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.
158pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String,
159160/// 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`]
169pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
170}
171172impl<'tcx, C: QueryCache> fmt::Debugfor QueryVTable<'tcx, C> {
173fn 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.
180f.write_str(self.name)
181 }
182}
183184impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> {
185#[inline(always)]
186pub fn will_cache_on_disk_for_key(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool {
187self.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key))
188 }
189190#[inline(always)]
191pub 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.
199self.try_load_from_disk_fn?(tcx, key, prev_index, index)
200 }
201202#[inline]
203pub fn is_loadable_from_disk(
204&self,
205 tcx: TyCtxt<'tcx>,
206 key: &C::Key,
207 index: SerializedDepNodeIndex,
208 ) -> bool {
209self.is_loadable_from_disk_fn.map_or(false, |f| f(tcx, key, index))
210 }
211212/// Synthesize an error value to let compilation continue after a cycle.
213pub 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 }
221222pub fn construct_dep_node(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> DepNode {
223DepNode::construct(tcx, self.dep_kind, key)
224 }
225}
226227pub struct QuerySystem<'tcx> {
228pub arenas: WorkerLocal<QueryArenas<'tcx>>,
229pub query_vtables: QueryVTables<'tcx>,
230231/// 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
235pub on_disk_cache: Option<OnDiskCache>,
236237pub local_providers: Providers,
238pub extern_providers: ExternProviders,
239240pub jobs: AtomicU64,
241}
242243#[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> {
245pub tcx: TyCtxt<'tcx>,
246pub span: Span,
247}
248249impl<'tcx> Dereffor TyCtxtAt<'tcx> {
250type Target = TyCtxt<'tcx>;
251#[inline(always)]
252fn deref(&self) -> &Self::Target {
253&self.tcx
254 }
255}
256257#[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> {
260pub tcx: TyCtxt<'tcx>,
261}
262263#[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> {
266pub tcx: TyCtxt<'tcx>,
267}
268269impl<'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)]
297pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> {
298TyCtxtEnsureOk { tcx: self }
299 }
300301/// 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)]
318pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> {
319TyCtxtEnsureDone { tcx: self }
320 }
321322/// Returns a transparent wrapper for `TyCtxt` which uses
323 /// `span` as the location of queries performed through it.
324#[inline(always)]
325pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
326TyCtxtAt { tcx: self, span }
327 }
328}
329330macro_rules!query_helper_param_ty {
331 (DefId) => { impl $crate::query::IntoQueryParam<DefId> };
332 (LocalDefId) => { impl $crate::query::IntoQueryParam<LocalDefId> };
333 ($K:ty) => { $K };
334}
335336macro_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.
340queries {
341 $(
342 $(#[$attr:meta])*
343fn $name:ident($($K:tt)*) -> $V:ty
344 {
345// Search for (QMODLIST) to find all occurrences of this query modifier list.
346anon: $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.
360non_queries { $($_:tt)* }
361 ) => {
362 $(
363#[allow(unused_lifetimes)]
364pub mod $name {
365use super::*;
366use $crate::query::erase::{self, Erased};
367368pub type Key<'tcx> = $($K)*;
369pub type Value<'tcx> = $V;
370371/// Key type used by provider functions in `local_providers`.
372 /// This query has the `separate_provide_extern` modifier.
373#[cfg($separate_provide_extern)]
374pub 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))]
378pub type LocalKey<'tcx> = Key<'tcx>;
379380/// 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)]
383pub 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))]
387pub type EnsureOkReturnType = ();
388389/// Type returned from query providers and loaded from disk-cache.
390#[cfg($arena_cache)]
391pub 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))]
395pub type ProvidedValue<'tcx> = Value<'tcx>;
396397/// 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)]
402pub 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)]
409let value: Value<'tcx> = {
410use $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 };
417418// Otherwise, the provided value is the value (and `tcx` is unused).
419#[cfg(not($arena_cache))]
420let value: Value<'tcx> = {
421let _ = tcx;
422 provided_value
423 };
424425 erase::erase_val(value)
426 }
427428pub type Cache<'tcx> =
429 <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
430431// 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")]
434const _: () = {
435if size_of::<Key<'static>>() > 88 {
436panic!("{}", concat!(
437"the query `",
438stringify!($name),
439"` has a key type `",
440stringify!($($K)*),
441"` that is too large"
442));
443 }
444 };
445446// 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"))]
450const _: () = {
451if size_of::<Value<'static>>() > 64 {
452panic!("{}", concat!(
453"the query `",
454stringify!($name),
455"` has a value type `",
456stringify!($V),
457"` that is too large"
458));
459 }
460 };
461 }
462 )*
463464/// Holds per-query arenas for queries with the `arena_cache` modifier.
465#[derive(Default)]
466pub struct QueryArenas<'tcx> {
467 $(
468// Use the `ArenaCached` helper trait to determine the arena's value type.
469#[cfg($arena_cache)]
470pub $name: TypedArena<
471 <$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
472 >,
473 )*
474 }
475476impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
477 $(
478 $(#[$attr])*
479#[inline(always)]
480pub fn $name(
481self,
482 key: query_helper_param_ty!($($K)*),
483 ) -> $crate::queries::$name::EnsureOkReturnType {
484485#[cfg($return_result_from_ensure_ok)]
486let ensure_fn = crate::query::inner::query_ensure_error_guaranteed;
487#[cfg(not($return_result_from_ensure_ok))]
488let ensure_fn = crate::query::inner::query_ensure;
489490 ensure_fn(
491self.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 }
499500impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
501 $(
502 $(#[$attr])*
503#[inline(always)]
504pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
505crate::query::inner::query_ensure(
506self.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 }
514515impl<'tcx> TyCtxt<'tcx> {
516 $(
517 $(#[$attr])*
518#[inline(always)]
519 #[must_use]
520pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
521self.at(DUMMY_SP).$name(key)
522 }
523 )*
524 }
525526impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
527 $(
528 $(#[$attr])*
529#[inline(always)]
530pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
531use $crate::query::{erase, inner};
532533 erase::restore_val::<$V>(inner::query_get_at(
534self.tcx,
535self.span,
536&self.tcx.query_system.query_vtables.$name,
537$crate::query::IntoQueryParam::into_query_param(key),
538 ))
539 }
540 )*
541 }
542543 $(
544#[cfg($feedable)]
545impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy>
546TyCtxtFeed<'tcx, K>
547 {
548 $(#[$attr])*
549#[inline(always)]
550pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
551let key = self.key().into_query_param();
552let erased_value = $name::provided_to_erased(self.tcx, value);
553$crate::query::inner::query_feed(
554self.tcx,
555 dep_graph::DepKind::$name,
556&self.tcx.query_system.query_vtables.$name,
557 key,
558 erased_value,
559 );
560 }
561 }
562 )*
563564/// Holds a `QueryVTable` for each query.
565pub struct QueryVTables<'tcx> {
566 $(
567pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Cache<'tcx>>,
568 )*
569 }
570571pub 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.
575pub $name: for<'tcx> fn(
576TyCtxt<'tcx>,
577$name::LocalKey<'tcx>,
578 ) -> $name::ProvidedValue<'tcx>,
579 )*
580 }
581582pub struct ExternProviders {
583 $(
584#[cfg($separate_provide_extern)]
585pub $name: for<'tcx> fn(
586TyCtxt<'tcx>,
587$name::Key<'tcx>,
588 ) -> $name::ProvidedValue<'tcx>,
589 )*
590 }
591592impl Default for Providers {
593fn default() -> Self {
594 Providers {
595 $(
596$name: |_, key| {
597$crate::query::plumbing::default_query(stringify!($name), &key)
598 },
599 )*
600 }
601 }
602 }
603604impl Default for ExternProviders {
605fn default() -> Self {
606 ExternProviders {
607 $(
608#[cfg($separate_provide_extern)]
609$name: |_, key| $crate::query::plumbing::default_extern_query(
610stringify!($name),
611&key,
612 ),
613 )*
614 }
615 }
616 }
617618impl Copy for Providers {}
619impl Clone for Providers {
620fn clone(&self) -> Self { *self }
621 }
622623impl Copy for ExternProviders {}
624impl Clone for ExternProviders {
625fn clone(&self) -> Self { *self }
626 }
627 };
628}
629630mod sealed {
631use rustc_hir::def_id::{LocalModDefId, ModDefId};
632633use super::{DefId, LocalDefId, OwnerId};
634635/// 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.
639pub trait IntoQueryParam<P> {
640fn into_query_param(self) -> P;
641 }
642643impl<P> IntoQueryParam<P> for P {
644#[inline(always)]
645fn into_query_param(self) -> P {
646self647 }
648 }
649650impl IntoQueryParam<LocalDefId> for OwnerId {
651#[inline(always)]
652fn into_query_param(self) -> LocalDefId {
653self.def_id
654 }
655 }
656657impl IntoQueryParam<DefId> for LocalDefId {
658#[inline(always)]
659fn into_query_param(self) -> DefId {
660self.to_def_id()
661 }
662 }
663664impl IntoQueryParam<DefId> for OwnerId {
665#[inline(always)]
666fn into_query_param(self) -> DefId {
667self.to_def_id()
668 }
669 }
670671impl IntoQueryParam<DefId> for ModDefId {
672#[inline(always)]
673fn into_query_param(self) -> DefId {
674self.to_def_id()
675 }
676 }
677678impl IntoQueryParam<DefId> for LocalModDefId {
679#[inline(always)]
680fn into_query_param(self) -> DefId {
681self.to_def_id()
682 }
683 }
684685impl IntoQueryParam<LocalDefId> for LocalModDefId {
686#[inline(always)]
687fn into_query_param(self) -> LocalDefId {
688self.into()
689 }
690 }
691}
692693#[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);
695696#[cold]
697pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
698crate::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}
705706#[cold]
707pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
708crate::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}