blob: e217ee189476406ba815faa4b864183c260072bb [file] [edit]
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>,
}