| use std::fmt; | |
| use std::ops::Deref; | |
| use rustc_data_structures::fingerprint::Fingerprint; | |
| use rustc_data_structures::fx::FxIndexMap; | |
| use rustc_data_structures::hash_table::HashTable; | |
| use rustc_data_structures::sharded::Sharded; | |
| use rustc_data_structures::sync::{AtomicU64, Lock, WorkerLocal}; | |
| use rustc_errors::Diag; | |
| use rustc_hir::def_id::LocalDefId; | |
| use rustc_span::Span; | |
| use crate::dep_graph::{DepKind, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex}; | |
| use crate::ich::StableHashState; | |
| use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey}; | |
| use crate::query::on_disk_cache::OnDiskCache; | |
| use crate::query::{IntoQueryKey, QueryCache, QueryJob, QueryKey, QueryStackFrame}; | |
| use crate::ty::{self, TyCtxt}; | |
| /// For a particular query, keeps track of "active" keys, i.e. keys whose | |
| /// evaluation has started but has not yet finished successfully. | |
| /// | |
| /// (Successful query evaluation for a key is represented by an entry in the | |
| /// query's in-memory cache.) | |
| pub struct QueryState<'tcx, K> { | |
| pub active: Sharded<HashTable<(K, ActiveKeyStatus<'tcx>)>>, | |
| } | |
| impl<'tcx, K> Default for QueryState<'tcx, K> { | |
| fn default() -> QueryState<'tcx, K> { | |
| QueryState { active: Default::default() } | |
| } | |
| } | |
| /// For a particular query and key, tracks the status of a query evaluation | |
| /// that has started, but has not yet finished successfully. | |
| /// | |
| /// (Successful query evaluation for a key is represented by an entry in the | |
| /// query's in-memory cache.) | |
| pub enum ActiveKeyStatus<'tcx> { | |
| /// Some thread is already evaluating the query for this key. | |
| /// | |
| /// The enclosed [`QueryJob`] can be used to wait for it to finish. | |
| Started(QueryJob<'tcx>), | |
| /// The query panicked. Queries trying to wait on this will raise a fatal error which will | |
| /// silently panic. | |
| Poisoned, | |
| } | |
| #[derive(Debug)] | |
| pub struct Cycle<'tcx> { | |
| /// The query and related span that uses the cycle. | |
| pub usage: Option<QueryStackFrame<'tcx>>, | |
| /// The span here corresponds to the reason for which this query was required. | |
| pub frames: Vec<QueryStackFrame<'tcx>>, | |
| } | |
| #[derive(Debug)] | |
| pub enum QueryMode { | |
| /// This is a normal query call to `tcx.$query(..)` or `tcx.at(span).$query(..)`. | |
| Get, | |
| /// This is a call to `tcx.ensure_ok().$query(..)`. | |
| EnsureOk, | |
| } | |
| /// Stores data and metadata (e.g. function pointers) for a particular query. | |
| pub struct QueryVTable<'tcx, C: QueryCache> { | |
| pub name: &'static str, | |
| /// True if this query has the `eval_always` modifier. | |
| pub eval_always: bool, | |
| /// True if this query has the `depth_limit` modifier. | |
| pub depth_limit: bool, | |
| /// True if this query has the `feedable` modifier. | |
| pub feedable: bool, | |
| pub cache_on_disk_local: bool, | |
| pub separate_provide_extern: bool, | |
| pub dep_kind: DepKind, | |
| pub state: QueryState<'tcx, C::Key>, | |
| pub cache: C, | |
| /// Function pointer that actually calls this query's provider. | |
| /// Also performs some associated secondary tasks; see the macro-defined | |
| /// implementation in `mod invoke_provider_fn` for more details. | |
| /// | |
| /// This should be the only code that calls the provider function. | |
| pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, | |
| /// Function pointer that tries to load a query value from disk. | |
| /// | |
| /// This should only be called after a successful check of [`Self::will_cache_on_disk_for_key`]. | |
| pub try_load_from_disk_fn: | |
| fn(tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) -> Option<C::Value>, | |
| /// Function pointer that hashes this query's result values. | |
| /// | |
| /// For `no_hash` queries, this function pointer is None. | |
| pub hash_value_fn: Option<fn(&mut StableHashState<'_>, &C::Value) -> Fingerprint>, | |
| /// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if | |
| /// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative | |
| /// error is created and emitted). A value may be returned, or (more commonly) the function may | |
| /// just abort after emitting the error. | |
| pub handle_cycle_error_fn: | |
| fn(tcx: TyCtxt<'tcx>, key: C::Key, cycle: Cycle<'tcx>, error: Diag<'_>) -> C::Value, | |
| pub format_value: fn(&C::Value) -> String, | |
| pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>, | |
| /// Function pointer that is called by the query methods on [`TyCtxt`] and | |
| /// friends[^1], after they have checked the in-memory cache and found no | |
| /// existing value for this key. | |
| /// | |
| /// Transitive responsibilities include trying to load a disk-cached value | |
| /// if possible (incremental only), invoking the query provider if necessary, | |
| /// and putting the obtained value into the in-memory cache. | |
| /// | |
| /// [^1]: [`TyCtxt`], [`TyCtxtAt`], [`TyCtxtEnsureOk`], [`TyCtxtEnsureDone`] | |
| pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>, | |
| } | |
| impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { | |
| pub fn will_cache_on_disk_for_key(&self, key: C::Key) -> bool { | |
| self.cache_on_disk_local && (!self.separate_provide_extern || key.as_local_key().is_some()) | |
| } | |
| } | |
| impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| // When debug-printing a query vtable (e.g. for ICE or tracing), | |
| // just print the query name to know what query we're dealing with. | |
| // The other fields and flags are probably just unhelpful noise. | |
| // | |
| // If there is need for a more detailed dump of all flags and fields, | |
| // consider writing a separate dump method and calling it explicitly. | |
| f.write_str(self.name) | |
| } | |
| } | |
| pub struct QuerySystem<'tcx> { | |
| pub arenas: WorkerLocal<QueryArenas<'tcx>>, | |
| pub query_vtables: QueryVTables<'tcx>, | |
| /// Side-effect associated with each [`DepKind::SideEffect`] node in the | |
| /// current incremental-compilation session. Side effects will be written | |
| /// to disk, and loaded by [`OnDiskCache`] in the next session. | |
| /// | |
| /// Always empty if incremental compilation is off. | |
| pub side_effects: Lock<FxIndexMap<DepNodeIndex, QuerySideEffect>>, | |
| /// This provides access to the incremental compilation on-disk cache for query results. | |
| /// Do not access this directly. It is only meant to be used by | |
| /// `DepGraph::try_mark_green()` and the query infrastructure. | |
| /// This is `None` if we are not incremental compilation mode | |
| pub on_disk_cache: Option<OnDiskCache>, | |
| pub local_providers: Providers, | |
| pub extern_providers: ExternProviders, | |
| pub jobs: AtomicU64, | |
| pub cycle_handler_nesting: Lock<u8>, | |
| } | |
| #[derive(Copy, Clone)] | |
| pub struct TyCtxtAt<'tcx> { | |
| pub tcx: TyCtxt<'tcx>, | |
| pub span: Span, | |
| } | |
| impl<'tcx> Deref for TyCtxtAt<'tcx> { | |
| type Target = TyCtxt<'tcx>; | |
| #[inline(always)] | |
| fn deref(&self) -> &Self::Target { | |
| &self.tcx | |
| } | |
| } | |
| #[derive(Copy, Clone)] | |
| #[must_use] | |
| pub struct TyCtxtEnsureOk<'tcx> { | |
| pub tcx: TyCtxt<'tcx>, | |
| } | |
| #[derive(Copy, Clone)] | |
| #[must_use] | |
| pub struct TyCtxtEnsureResult<'tcx> { | |
| pub tcx: TyCtxt<'tcx>, | |
| } | |
| #[derive(Copy, Clone)] | |
| #[must_use] | |
| pub struct TyCtxtEnsureDone<'tcx> { | |
| pub tcx: TyCtxt<'tcx>, | |
| } | |
| impl<'tcx> TyCtxtEnsureOk<'tcx> { | |
| pub fn typeck(self, def_id: impl IntoQueryKey<LocalDefId>) { | |
| self.typeck_root( | |
| self.tcx.typeck_root_def_id(def_id.into_query_key().to_def_id()).expect_local(), | |
| ) | |
| } | |
| } | |
| impl<'tcx> TyCtxt<'tcx> { | |
| pub fn typeck(self, def_id: impl IntoQueryKey<LocalDefId>) -> &'tcx ty::TypeckResults<'tcx> { | |
| self.typeck_root( | |
| self.typeck_root_def_id(def_id.into_query_key().to_def_id()).expect_local(), | |
| ) | |
| } | |
| /// Returns a transparent wrapper for `TyCtxt` which uses | |
| /// `span` as the location of queries performed through it. | |
| #[inline(always)] | |
| pub fn at(self, span: Span) -> TyCtxtAt<'tcx> { | |
| TyCtxtAt { tcx: self, span } | |
| } | |
| /// FIXME: `ensure_ok`'s effects are subtle. Is this comment fully accurate? | |
| /// | |
| /// Wrapper that calls queries in a special "ensure OK" mode, for callers | |
| /// that don't need the return value and just want to invoke a query for | |
| /// its potential side-effect of emitting fatal errors. | |
| /// | |
| /// This can be more efficient than a normal query call, because if the | |
| /// query's inputs are all green, the call can return immediately without | |
| /// needing to obtain a value (by decoding one from disk or by executing | |
| /// the query). | |
| /// | |
| /// (As with all query calls, execution is also skipped if the query result | |
| /// is already cached in memory.) | |
| /// | |
| /// ## WARNING | |
| /// A subsequent normal call to the same query might still cause it to be | |
| /// executed! This can occur when the inputs are all green, but the query's | |
| /// result is not cached on disk, so the query must be executed to obtain a | |
| /// return value. | |
| /// | |
| /// Therefore, this call mode is not appropriate for callers that want to | |
| /// ensure that the query is _never_ executed in the future. | |
| #[inline(always)] | |
| pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> { | |
| TyCtxtEnsureOk { tcx: self } | |
| } | |
| /// This is a variant of `ensure_ok` only usable with queries that return | |
| /// `Result<_, ErrorGuaranteed>`. Queries calls through this function will | |
| /// return `Result<(), ErrorGuaranteed>`. I.e. the error status is returned | |
| /// but nothing else. As with `ensure_ok`, this can be more efficient than | |
| /// a normal query call. | |
| #[inline(always)] | |
| pub fn ensure_result(self) -> TyCtxtEnsureResult<'tcx> { | |
| TyCtxtEnsureResult { tcx: self } | |
| } | |
| /// Wrapper that calls queries where callers don't need the return value and | |
| /// just want to guarantee that the query won't be executed in the future. | |
| /// | |
| /// This is useful for queries that read from a [`Steal`] value, to ensure | |
| /// that they are executed before the query that will steal the value. | |
| /// | |
| /// Currently this causes the query to be executed normally, but this behavior may change. | |
| /// | |
| /// [`Steal`]: rustc_data_structures::steal::Steal | |
| #[inline(always)] | |
| pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> { | |
| TyCtxtEnsureDone { tcx: self } | |
| } | |
| } | |
| macro_rules! maybe_into_query_key { | |
| (DefId) => { impl $crate::query::IntoQueryKey<DefId> }; | |
| (LocalDefId) => { impl $crate::query::IntoQueryKey<LocalDefId> }; | |
| ($K:ty) => { $K }; | |
| } | |
| macro_rules! define_callbacks { | |
| ( | |
| // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that | |
| // `maybe_into_query_key!` can match on specific type names. | |
| queries { | |
| $( | |
| $(#[$attr:meta])* | |
| fn $name:ident($($K:tt)*) -> $V:ty | |
| { | |
| // Search for (QMODLIST) to find all occurrences of this query modifier list. | |
| arena_cache: $arena_cache:literal, | |
| cache_on_disk: $cache_on_disk:literal, | |
| depth_limit: $depth_limit:literal, | |
| desc: $desc:expr, | |
| eval_always: $eval_always:literal, | |
| feedable: $feedable:literal, | |
| handle_cycle_error: $handle_cycle_error:literal, | |
| no_force: $no_force:literal, | |
| no_hash: $no_hash:literal, | |
| returns_error_guaranteed: $returns_error_guaranteed:literal, | |
| separate_provide_extern: $separate_provide_extern:literal, | |
| } | |
| )* | |
| } | |
| // Non-queries are unused here. | |
| non_queries { $($_:tt)* } | |
| ) => { | |
| $( | |
| pub mod $name { | |
| use super::*; | |
| use $crate::query::erase::{self, Erased}; | |
| pub type Key<'tcx> = $($K)*; | |
| pub type Value<'tcx> = $V; | |
| /// Key type used by provider functions in `local_providers`. | |
| /// This query has the `separate_provide_extern` modifier. | |
| #[cfg($separate_provide_extern)] | |
| pub type LocalKey<'tcx> = | |
| <Key<'tcx> as $crate::query::QueryKey>::LocalQueryKey; | |
| /// Key type used by provider functions in `local_providers`. | |
| #[cfg(not($separate_provide_extern))] | |
| pub type LocalKey<'tcx> = Key<'tcx>; | |
| /// Type returned from query providers and loaded from disk-cache. | |
| #[cfg($arena_cache)] | |
| pub type ProvidedValue<'tcx> = | |
| <Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided; | |
| /// Type returned from query providers and loaded from disk-cache. | |
| #[cfg(not($arena_cache))] | |
| pub type ProvidedValue<'tcx> = Value<'tcx>; | |
| pub type Cache<'tcx> = | |
| <Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>; | |
| /// This helper function takes a value returned by the query provider | |
| /// (or loaded from disk, or supplied by query feeding), allocates | |
| /// it in an arena if requested by the `arena_cache` modifier, and | |
| /// then returns an erased copy of it. | |
| #[inline(always)] | |
| pub fn provided_to_erased<'tcx>( | |
| tcx: TyCtxt<'tcx>, | |
| provided_value: ProvidedValue<'tcx>, | |
| ) -> Erased<Value<'tcx>> { | |
| // For queries with the `arena_cache` modifier, store the | |
| // provided value in an arena and get a reference to it. | |
| #[cfg($arena_cache)] | |
| let value: Value<'tcx> = { | |
| use $crate::query::arena_cached::ArenaCached; | |
| <Value<'tcx> as ArenaCached>::alloc_in_arena( | |
| tcx, | |
| &tcx.query_system.arenas.$name, | |
| provided_value, | |
| ) | |
| }; | |
| // Otherwise, the provided value is the value (and `tcx` is unused). | |
| #[cfg(not($arena_cache))] | |
| let value: Value<'tcx> = { | |
| let _ = tcx; | |
| provided_value | |
| }; | |
| erase::erase_val(value) | |
| } | |
| // Ensure that keys grow no larger than 88 bytes by accident. | |
| // Increase this limit if necessary, but do try to keep the size low if possible | |
| #[cfg(target_pointer_width = "64")] | |
| const _: () = { | |
| if size_of::<Key<'static>>() > 88 { | |
| panic!("{}", concat!( | |
| "the query `", | |
| stringify!($name), | |
| "` has a key type `", | |
| stringify!($($K)*), | |
| "` that is too large" | |
| )); | |
| } | |
| }; | |
| // Ensure that values grow no larger than 64 bytes by accident. | |
| // Increase this limit if necessary, but do try to keep the size low if possible | |
| #[cfg(target_pointer_width = "64")] | |
| #[cfg(not(feature = "rustc_randomized_layouts"))] | |
| const _: () = { | |
| if size_of::<Value<'static>>() > 64 { | |
| panic!("{}", concat!( | |
| "the query `", | |
| stringify!($name), | |
| "` has a value type `", | |
| stringify!($V), | |
| "` that is too large" | |
| )); | |
| } | |
| }; | |
| } | |
| )* | |
| /// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a | |
| /// number. | |
| #[allow(non_camel_case_types)] | |
| #[derive(Clone, Copy, Debug)] | |
| pub enum TaggedQueryKey<'tcx> { | |
| $( | |
| $name($name::Key<'tcx>), | |
| )* | |
| } | |
| impl<'tcx> TaggedQueryKey<'tcx> { | |
| /// Returns the name of the query this key is tagged with. | |
| /// | |
| /// This is useful for error/debug output, but don't use it to check for | |
| /// specific query names. Instead, match on the `TaggedQueryKey` variant. | |
| pub fn query_name(&self) -> &'static str { | |
| match self { | |
| $( | |
| TaggedQueryKey::$name(_) => stringify!($name), | |
| )* | |
| } | |
| } | |
| /// Formats a human-readable description of this query and its key, as | |
| /// specified by the `desc` query modifier. | |
| /// | |
| /// Used when reporting query cycle errors and similar problems. | |
| pub fn description(&self, tcx: TyCtxt<'tcx>) -> String { | |
| let (name, description) = ty::print::with_no_queries!(match self { | |
| $( | |
| TaggedQueryKey::$name(key) => (stringify!($name), ($desc)(tcx, *key)), | |
| )* | |
| }); | |
| if tcx.sess.verbose_internals() { | |
| format!("{description} [{name:?}]") | |
| } else { | |
| description | |
| } | |
| } | |
| /// Calls `self.description` or returns a fallback if there was a fatal error | |
| pub fn catch_description(&self, tcx: TyCtxt<'tcx>) -> String { | |
| catch_fatal_errors(|| self.description(tcx)).unwrap_or_else(|_| format!("<error describing {}>", self.query_name())) | |
| } | |
| /// Returns the default span for this query if `span` is a dummy span. | |
| pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span { | |
| if !span.is_dummy() { | |
| return span | |
| } | |
| if let TaggedQueryKey::def_span(..) = self { | |
| // The `def_span` query is used to calculate `default_span`, | |
| // so exit to avoid infinite recursion. | |
| return DUMMY_SP | |
| } | |
| match self { | |
| $( | |
| TaggedQueryKey::$name(key) => | |
| $crate::query::QueryKey::default_span(key, tcx), | |
| )* | |
| } | |
| } | |
| /// Calls `self.default_span` or returns `DUMMY_SP` if there was a fatal error | |
| pub fn catch_default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span { | |
| catch_fatal_errors(|| self.default_span(tcx, span)).unwrap_or(DUMMY_SP) | |
| } | |
| } | |
| /// Holds a `QueryVTable` for each query. | |
| pub struct QueryVTables<'tcx> { | |
| $( | |
| pub $name: $crate::query::QueryVTable<'tcx, $name::Cache<'tcx>>, | |
| )* | |
| } | |
| /// Holds per-query arenas for queries with the `arena_cache` modifier. | |
| #[derive(Default)] | |
| pub struct QueryArenas<'tcx> { | |
| $( | |
| // Use the `ArenaCached` helper trait to determine the arena's value type. | |
| #[cfg($arena_cache)] | |
| pub $name: TypedArena< | |
| <$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated, | |
| >, | |
| )* | |
| } | |
| pub struct Providers { | |
| $( | |
| /// This is the provider for the query. Use `Find references` on this to | |
| /// navigate between the provider assignment and the query definition. | |
| pub $name: for<'tcx> fn( | |
| TyCtxt<'tcx>, | |
| $name::LocalKey<'tcx>, | |
| ) -> $name::ProvidedValue<'tcx>, | |
| )* | |
| } | |
| pub struct ExternProviders { | |
| $( | |
| #[cfg($separate_provide_extern)] | |
| pub $name: for<'tcx> fn( | |
| TyCtxt<'tcx>, | |
| $name::Key<'tcx>, | |
| ) -> $name::ProvidedValue<'tcx>, | |
| )* | |
| } | |
| impl Default for Providers { | |
| fn default() -> Self { | |
| Providers { | |
| $( | |
| $name: |_, key| { | |
| $crate::query::plumbing::default_query(stringify!($name), &key) | |
| }, | |
| )* | |
| } | |
| } | |
| } | |
| impl Default for ExternProviders { | |
| fn default() -> Self { | |
| ExternProviders { | |
| $( | |
| #[cfg($separate_provide_extern)] | |
| $name: |_, key| $crate::query::plumbing::default_extern_query( | |
| stringify!($name), | |
| &key, | |
| ), | |
| )* | |
| } | |
| } | |
| } | |
| impl Copy for Providers {} | |
| impl Clone for Providers { | |
| fn clone(&self) -> Self { *self } | |
| } | |
| impl Copy for ExternProviders {} | |
| impl Clone for ExternProviders { | |
| fn clone(&self) -> Self { *self } | |
| } | |
| impl<'tcx> TyCtxt<'tcx> { | |
| $( | |
| $(#[$attr])* | |
| #[inline(always)] | |
| #[must_use] | |
| pub fn $name(self, key: maybe_into_query_key!($($K)*)) -> $V { | |
| self.at(DUMMY_SP).$name(key) | |
| } | |
| )* | |
| } | |
| impl<'tcx> $crate::query::TyCtxtAt<'tcx> { | |
| $( | |
| $(#[$attr])* | |
| #[inline(always)] | |
| pub fn $name(self, key: maybe_into_query_key!($($K)*)) -> $V { | |
| use $crate::query::{erase, inner}; | |
| erase::restore_val::<$V>(inner::query_get_at( | |
| self.tcx, | |
| self.span, | |
| &self.tcx.query_system.query_vtables.$name, | |
| $crate::query::IntoQueryKey::into_query_key(key), | |
| )) | |
| } | |
| )* | |
| } | |
| impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> { | |
| $( | |
| $(#[$attr])* | |
| #[inline(always)] | |
| pub fn $name(self, key: maybe_into_query_key!($($K)*)) { | |
| $crate::query::inner::query_ensure_ok( | |
| self.tcx, | |
| &self.tcx.query_system.query_vtables.$name, | |
| $crate::query::IntoQueryKey::into_query_key(key), | |
| ) | |
| } | |
| )* | |
| } | |
| // Only defined when the `returns_error_guaranteed` modifier is present. | |
| impl<'tcx> $crate::query::TyCtxtEnsureResult<'tcx> { | |
| $( | |
| #[cfg($returns_error_guaranteed)] | |
| $(#[$attr])* | |
| #[inline(always)] | |
| pub fn $name( | |
| self, | |
| key: maybe_into_query_key!($($K)*), | |
| ) -> Result<(), rustc_errors::ErrorGuaranteed> { | |
| $crate::query::inner::query_ensure_result( | |
| self.tcx, | |
| &self.tcx.query_system.query_vtables.$name, | |
| $crate::query::IntoQueryKey::into_query_key(key), | |
| ) | |
| } | |
| )* | |
| } | |
| impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> { | |
| $( | |
| $(#[$attr])* | |
| #[inline(always)] | |
| pub fn $name(self, key: maybe_into_query_key!($($K)*)) { | |
| // This has the same implementation as `tcx.$query(..)` as it isn't currently | |
| // beneficial to have an optimized variant due to how promotion works. | |
| let _ = self.tcx.$name(key); | |
| } | |
| )* | |
| } | |
| $( | |
| // Only defined when the `feedable` modifier is present. | |
| #[cfg($feedable)] | |
| impl<'tcx, K: $crate::query::IntoQueryKey<$name::Key<'tcx>> + Copy> | |
| TyCtxtFeed<'tcx, K> | |
| { | |
| $(#[$attr])* | |
| #[inline(always)] | |
| pub fn $name(self, value: $name::ProvidedValue<'tcx>) { | |
| $crate::query::inner::query_feed( | |
| self.tcx, | |
| &self.tcx.query_system.query_vtables.$name, | |
| self.key().into_query_key(), | |
| $name::provided_to_erased(self.tcx, value), | |
| ); | |
| } | |
| } | |
| )* | |
| }; | |
| } | |
| // Re-export `macro_rules!` macros as normal items, so that they can be imported normally. | |
| pub(crate) use define_callbacks; | |
| pub(crate) use maybe_into_query_key; | |
| #[cold] | |
| pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! { | |
| bug!( | |
| "`tcx.{name}({key:?})` is not supported for this key;\n\ | |
| hint: 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.\n\ | |
| If that's not the case, {name} was likely never assigned to a provider function.\n", | |
| ) | |
| } | |
| #[cold] | |
| pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! { | |
| bug!( | |
| "`tcx.{name}({key:?})` unsupported by its crate; \ | |
| perhaps the `{name}` query was never assigned a provider function", | |
| ) | |
| } |