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}
6465pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool;
6667pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn(
68 tcx: TyCtxt<'tcx>,
69 key: &Key,
70 prev_index: SerializedDepNodeIndex,
71 index: DepNodeIndex,
72) -> Option<Value>;
7374pub type IsLoadableFromDiskFn<'tcx, Key> =
75fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool;
7677pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
7879#[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)]
80pub struct CycleError<I = QueryStackFrameExtra> {
81/// The query and related span that uses the cycle.
82pub usage: Option<(Span, QueryStackFrame<I>)>,
83pub cycle: Vec<QueryInfo<I>>,
84}
8586impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
87pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
88CycleError {
89 usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())),
90 cycle: self.cycle.iter().map(|info| info.lift()).collect(),
91 }
92 }
93}
9495#[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)]
96pub enum QueryMode {
97/// This is a normal query call to `tcx.$query(..)` or `tcx.at(span).$query(..)`.
98Get,
99/// This is a call to `tcx.ensure_ok().$query(..)` or `tcx.ensure_done().$query(..)`.
100Ensure { ensure_mode: EnsureMode },
101}
102103/// Distinguishes between `tcx.ensure_ok()` and `tcx.ensure_done()` in shared
104/// code paths that handle both modes.
105#[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)]
106pub enum EnsureMode {
107/// Corresponds to [`TyCtxt::ensure_ok`].
108Ok,
109/// Corresponds to [`TyCtxt::ensure_done`].
110Done,
111}
112113/// Stores data and metadata (e.g. function pointers) for a particular query.
114pub struct QueryVTable<'tcx, C: QueryCache> {
115pub name: &'static str,
116117/// True if this query has the `anon` modifier.
118pub anon: bool,
119/// True if this query has the `eval_always` modifier.
120pub eval_always: bool,
121/// True if this query has the `depth_limit` modifier.
122pub depth_limit: bool,
123/// True if this query has the `feedable` modifier.
124pub feedable: bool,
125126pub dep_kind: DepKind,
127/// How this query deals with query cycle errors.
128pub cycle_error_handling: CycleErrorHandling,
129pub state: QueryState<'tcx, C::Key>,
130pub cache: C,
131pub will_cache_on_disk_for_key_fn: Option<WillCacheOnDiskForKeyFn<'tcx, C::Key>>,
132133/// Function pointer that calls `tcx.$query(key)` for this query and
134 /// discards the returned value.
135 ///
136 /// This is a weird thing to be doing, and probably not what you want.
137 /// It is used for loading query results from disk-cache in some cases.
138pub call_query_method_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key),
139140/// Function pointer that actually calls this query's provider.
141 /// Also performs some associated secondary tasks; see the macro-defined
142 /// implementation in `mod invoke_provider_fn` for more details.
143 ///
144 /// This should be the only code that calls the provider function.
145pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
146147pub try_load_from_disk_fn: Option<TryLoadFromDiskFn<'tcx, C::Key, C::Value>>,
148pub is_loadable_from_disk_fn: Option<IsLoadableFromDiskFn<'tcx, C::Key>>,
149pub hash_result: HashResult<C::Value>,
150pub 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}
335336// Expands to `$yes` if the `arena_cache` modifier is present, `$no` otherwise.
337macro_rules!if_arena_cache {
338 ([] $then:tt $no:tt) => { $no };
339 ([(arena_cache) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
340 ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
341if_arena_cache!([$($modifiers)*] $yes $no)
342 };
343}
344345// Expands to `$yes` if the `separate_provide_extern` modifier is present, `$no` otherwise.
346macro_rules!if_separate_provide_extern {
347 ([] $then:tt $no:tt) => { $no };
348 ([(separate_provide_extern) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
349 ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
350if_separate_provide_extern!([$($modifiers)*] $yes $no)
351 };
352}
353354// Expands to `$yes` if the `return_result_from_ensure_ok` modifier is present, `$no` otherwise.
355macro_rules!if_return_result_from_ensure_ok {
356 ([] $then:tt $no:tt) => { $no };
357 ([(return_result_from_ensure_ok) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
358 ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
359if_return_result_from_ensure_ok!([$($modifiers)*] $yes $no)
360 };
361}
362363// Expands to `$item` if the `feedable` modifier is present.
364macro_rules!item_if_feedable {
365 ([] $($item:tt)*) => {};
366 ([(feedable) $($rest:tt)*] $($item:tt)*) => {
367 $($item)*
368 };
369 ([$other:tt $($modifiers:tt)*] $($item:tt)*) => {
370item_if_feedable! { [$($modifiers)*] $($item)* }
371 };
372}
373374macro_rules!define_callbacks {
375 (
376// You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
377 // `query_helper_param_ty!` can match on specific type names.
378$(
379 $(#[$attr:meta])*
380 [$($modifiers:tt)*]
381fn $name:ident($($K:tt)*) -> $V:ty,
382 )*
383 ) => {
384 $(
385#[allow(unused_lifetimes)]
386pub mod $name {
387use super::*;
388use $crate::query::erase::{self, Erased};
389390pub type Key<'tcx> = $($K)*;
391pub type Value<'tcx> = $V;
392393pub type LocalKey<'tcx> = if_separate_provide_extern!(
394 [$($modifiers)*]
395 (<Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey)
396 (Key<'tcx>)
397 );
398399/// This type alias specifies the type returned from query providers and the type
400 /// used for decoding. For regular queries this is the declared returned type `V`,
401 /// but `arena_cache` will use `<V as ArenaCached>::Provided` instead.
402pub type ProvidedValue<'tcx> = if_arena_cache!(
403 [$($modifiers)*]
404 (<Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided)
405 (Value<'tcx>)
406 );
407408/// This helper function takes a value returned by the query provider
409 /// (or loaded from disk, or supplied by query feeding), allocates
410 /// it in an arena if requested by the `arena_cache` modifier, and
411 /// then returns an erased copy of it.
412#[inline(always)]
413pub fn provided_to_erased<'tcx>(
414 tcx: TyCtxt<'tcx>,
415 provided_value: ProvidedValue<'tcx>,
416 ) -> Erased<Value<'tcx>> {
417// For queries with the `arena_cache` modifier, store the
418 // provided value in an arena and get a reference to it.
419let value: Value<'tcx> = if_arena_cache!(
420 [$($modifiers)*]
421 {
422 <Value<'tcx> as $crate::query::arena_cached::ArenaCached>::
423 alloc_in_arena
424 (
425 tcx,
426&tcx.query_system.arenas.$name,
427 provided_value,
428 )
429 }
430 {
431// Otherwise, the provided value is the value (and `tcx` is unused).
432let _ = tcx;
433 provided_value
434 }
435 );
436 erase::erase_val(value)
437 }
438439pub type Cache<'tcx> =
440 <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
441442// Ensure that keys grow no larger than 88 bytes by accident.
443 // Increase this limit if necessary, but do try to keep the size low if possible
444#[cfg(target_pointer_width = "64")]
445const _: () = {
446if size_of::<Key<'static>>() > 88 {
447panic!("{}", concat!(
448"the query `",
449stringify!($name),
450"` has a key type `",
451stringify!($($K)*),
452"` that is too large"
453));
454 }
455 };
456457// Ensure that values grow no larger than 64 bytes by accident.
458 // Increase this limit if necessary, but do try to keep the size low if possible
459#[cfg(target_pointer_width = "64")]
460 #[cfg(not(feature = "rustc_randomized_layouts"))]
461const _: () = {
462if size_of::<Value<'static>>() > 64 {
463panic!("{}", concat!(
464"the query `",
465stringify!($name),
466"` has a value type `",
467stringify!($V),
468"` that is too large"
469));
470 }
471 };
472 }
473 )*
474475/// Holds per-query arenas for queries with the `arena_cache` modifier.
476#[derive(Default)]
477pub struct QueryArenas<'tcx> {
478 $(
479pub $name: if_arena_cache!(
480 [$($modifiers)*]
481// Use the `ArenaCached` helper trait to determine the arena's value type.
482(TypedArena<<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated>)
483// No arena for this query, so the field type is `()`.
484()
485 ),
486 )*
487 }
488489impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
490 $(
491 $(#[$attr])*
492#[inline(always)]
493pub fn $name(
494self,
495 key: query_helper_param_ty!($($K)*),
496 ) -> if_return_result_from_ensure_ok!(
497 [$($modifiers)*]
498 (Result<(), ErrorGuaranteed>)
499 ()
500 ) {
501if_return_result_from_ensure_ok!(
502 [$($modifiers)*]
503 (crate::query::inner::query_ensure_error_guaranteed)
504 (crate::query::inner::query_ensure)
505 )(
506self.tcx,
507&self.tcx.query_system.query_vtables.$name,
508$crate::query::IntoQueryParam::into_query_param(key),
509$crate::query::EnsureMode::Ok,
510 )
511 }
512 )*
513 }
514515impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
516 $(
517 $(#[$attr])*
518#[inline(always)]
519pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
520crate::query::inner::query_ensure(
521self.tcx,
522&self.tcx.query_system.query_vtables.$name,
523$crate::query::IntoQueryParam::into_query_param(key),
524$crate::query::EnsureMode::Done,
525 );
526 }
527 )*
528 }
529530impl<'tcx> TyCtxt<'tcx> {
531 $(
532 $(#[$attr])*
533#[inline(always)]
534 #[must_use]
535pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
536self.at(DUMMY_SP).$name(key)
537 }
538 )*
539 }
540541impl<'tcx> $crate::query::TyCtxtAt<'tcx> {
542 $(
543 $(#[$attr])*
544#[inline(always)]
545pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
546use $crate::query::{erase, inner};
547548 erase::restore_val::<$V>(inner::query_get_at(
549self.tcx,
550self.span,
551&self.tcx.query_system.query_vtables.$name,
552$crate::query::IntoQueryParam::into_query_param(key),
553 ))
554 }
555 )*
556 }
557558 $(
559item_if_feedable! {
560 [$($modifiers)*]
561impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy>
562TyCtxtFeed<'tcx, K>
563 {
564 $(#[$attr])*
565#[inline(always)]
566pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
567let key = self.key().into_query_param();
568let erased_value = $name::provided_to_erased(self.tcx, value);
569$crate::query::inner::query_feed(
570self.tcx,
571 dep_graph::DepKind::$name,
572&self.tcx.query_system.query_vtables.$name,
573 key,
574 erased_value,
575 );
576 }
577 }
578 }
579 )*
580581/// Holds a `QueryVTable` for each query.
582pub struct QueryVTables<'tcx> {
583 $(
584pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Cache<'tcx>>,
585 )*
586 }
587588pub struct Providers {
589 $(
590/// This is the provider for the query. Use `Find references` on this to
591 /// navigate between the provider assignment and the query definition.
592pub $name: for<'tcx> fn(
593TyCtxt<'tcx>,
594$name::LocalKey<'tcx>,
595 ) -> $name::ProvidedValue<'tcx>,
596 )*
597 }
598599pub struct ExternProviders {
600 $(
601pub $name: if_separate_provide_extern!(
602 [$($modifiers)*]
603 (for<'tcx> fn(TyCtxt<'tcx>, $name::Key<'tcx>) -> $name::ProvidedValue<'tcx>)
604 ()
605 ),
606 )*
607 }
608609impl Default for Providers {
610fn default() -> Self {
611 Providers {
612 $(
613$name: |_, key| {
614$crate::query::plumbing::default_query(stringify!($name), &key)
615 },
616 )*
617 }
618 }
619 }
620621impl Default for ExternProviders {
622fn default() -> Self {
623 ExternProviders {
624 $(
625$name: if_separate_provide_extern!(
626 [$($modifiers)*]
627 (|_, key| $crate::query::plumbing::default_extern_query(
628stringify!($name),
629&key
630 ))
631 ()
632 ),
633 )*
634 }
635 }
636 }
637638impl Copy for Providers {}
639impl Clone for Providers {
640fn clone(&self) -> Self { *self }
641 }
642643impl Copy for ExternProviders {}
644impl Clone for ExternProviders {
645fn clone(&self) -> Self { *self }
646 }
647 };
648}
649650// Each of these queries corresponds to a function pointer field in the
651// `Providers` struct for requesting a value of that type, and a method
652// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
653// which memoizes and does dep-graph tracking, wrapping around the actual
654// `Providers` that the driver creates (using several `rustc_*` crates).
655//
656// The result type of each query must implement `Clone`, and additionally
657// `ty::query::values::Value`, which produces an appropriate placeholder
658// (error) value if the query resulted in a query cycle.
659// Queries marked with `cycle_fatal` do not need the latter implementation,
660// as they will raise an fatal error on query cycles instead.
661662mod sealed {
663use rustc_hir::def_id::{LocalModDefId, ModDefId};
664665use super::{DefId, LocalDefId, OwnerId};
666667/// An analogue of the `Into` trait that's intended only for query parameters.
668 ///
669 /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
670 /// user call `to_def_id` to convert between them everywhere else.
671pub trait IntoQueryParam<P> {
672fn into_query_param(self) -> P;
673 }
674675impl<P> IntoQueryParam<P> for P {
676#[inline(always)]
677fn into_query_param(self) -> P {
678self679 }
680 }
681682impl IntoQueryParam<LocalDefId> for OwnerId {
683#[inline(always)]
684fn into_query_param(self) -> LocalDefId {
685self.def_id
686 }
687 }
688689impl IntoQueryParam<DefId> for LocalDefId {
690#[inline(always)]
691fn into_query_param(self) -> DefId {
692self.to_def_id()
693 }
694 }
695696impl IntoQueryParam<DefId> for OwnerId {
697#[inline(always)]
698fn into_query_param(self) -> DefId {
699self.to_def_id()
700 }
701 }
702703impl IntoQueryParam<DefId> for ModDefId {
704#[inline(always)]
705fn into_query_param(self) -> DefId {
706self.to_def_id()
707 }
708 }
709710impl IntoQueryParam<DefId> for LocalModDefId {
711#[inline(always)]
712fn into_query_param(self) -> DefId {
713self.to_def_id()
714 }
715 }
716717impl IntoQueryParam<LocalDefId> for LocalModDefId {
718#[inline(always)]
719fn into_query_param(self) -> LocalDefId {
720self.into()
721 }
722 }
723}
724725#[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)]
726pub struct CyclePlaceholder(pub ErrorGuaranteed);
727728#[cold]
729pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
730crate::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!(
731"`tcx.{name}({key:?})` is not supported for this key;\n\
732 hint: Queries can be either made to the local crate, or the external crate. \
733 This error means you tried to use it for one that's not supported.\n\
734 If that's not the case, {name} was likely never assigned to a provider function.\n",
735 )736}
737738#[cold]
739pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
740crate::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!(
741"`tcx.{name}({key:?})` unsupported by its crate; \
742 perhaps the `{name}` query was never assigned a provider function",
743 )744}