| use std::fmt; | |
| use rustc_data_structures::fingerprint::Fingerprint; | |
| use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; | |
| use rustc_data_structures::sync::{AtomicU64, Lock, WorkerLocal}; | |
| use rustc_errors::Diag; | |
| use rustc_span::{Span, Symbol}; | |
| use crate::dep_graph::{ | |
| DepKind, DepKindVTable, 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::{QueryCache, QueryCycle, QueryKey, QueryState}; | |
| use crate::ty::TyCtxt; | |
| #[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: QueryCycle<'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`], [`crate::query::TyCtxtAt`], [`crate::query::TyCtxtEnsureOk`], | |
| /// [`crate::query::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 dep_kind_vtables: &'tcx [DepKindVTable<'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>>, | |
| /// Enabled features that are used in the current compilation. | |
| /// | |
| /// The value is the `DepNodeIndex` of the node that encodes the used feature. | |
| pub used_features: Lock<FxHashMap<Symbol, DepNodeIndex>>, | |
| /// 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>, | |
| } |