Skip to main content

rustc_middle/query/
system.rs

1use std::fmt;
2
3use rustc_data_structures::fingerprint::Fingerprint;
4use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
5use rustc_data_structures::sync::{AtomicU64, Lock, WorkerLocal};
6use rustc_errors::Diag;
7use rustc_span::{Span, Symbol};
8
9use crate::dep_graph::{
10    DepKind, DepKindVTable, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex,
11};
12use crate::ich::StableHashState;
13use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
14use crate::query::on_disk_cache::OnDiskCache;
15use crate::query::{QueryCache, QueryCycle, QueryKey, QueryState};
16use crate::ty::TyCtxt;
17
18#[derive(#[automatically_derived]
impl ::core::fmt::Debug for QueryMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                QueryMode::Get => "Get",
                QueryMode::EnsureOk => "EnsureOk",
            })
    }
}Debug)]
19pub enum QueryMode {
20    /// This is a normal query call to `tcx.$query(..)` or `tcx.at(span).$query(..)`.
21    Get,
22    /// This is a call to `tcx.ensure_ok().$query(..)`.
23    EnsureOk,
24}
25
26/// Stores data and metadata (e.g. function pointers) for a particular query.
27pub struct QueryVTable<'tcx, C: QueryCache> {
28    pub name: &'static str,
29
30    /// True if this query has the `eval_always` modifier.
31    pub eval_always: bool,
32    /// True if this query has the `depth_limit` modifier.
33    pub depth_limit: bool,
34    /// True if this query has the `feedable` modifier.
35    pub feedable: bool,
36
37    pub cache_on_disk_local: bool,
38    pub separate_provide_extern: bool,
39
40    pub dep_kind: DepKind,
41    pub state: QueryState<'tcx, C::Key>,
42    pub cache: C,
43
44    /// Function pointer that actually calls this query's provider.
45    /// Also performs some associated secondary tasks; see the macro-defined
46    /// implementation in `mod invoke_provider_fn` for more details.
47    ///
48    /// This should be the only code that calls the provider function.
49    pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
50
51    /// Function pointer that tries to load a query value from disk.
52    ///
53    /// This should only be called after a successful check of [`Self::will_cache_on_disk_for_key`].
54    pub try_load_from_disk_fn:
55        fn(tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) -> Option<C::Value>,
56
57    /// Function pointer that hashes this query's result values.
58    ///
59    /// For `no_hash` queries, this function pointer is None.
60    pub hash_value_fn: Option<fn(&mut StableHashState<'_>, &C::Value) -> Fingerprint>,
61
62    /// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if
63    /// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative
64    /// error is created and emitted). A value may be returned, or (more commonly) the function may
65    /// just abort after emitting the error.
66    pub handle_cycle_error_fn:
67        fn(tcx: TyCtxt<'tcx>, key: C::Key, cycle: QueryCycle<'tcx>, error: Diag<'_>) -> C::Value,
68
69    pub format_value: fn(&C::Value) -> String,
70
71    pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>,
72
73    /// Function pointer that is called by the query methods on [`TyCtxt`] and
74    /// friends[^1], after they have checked the in-memory cache and found no
75    /// existing value for this key.
76    ///
77    /// Transitive responsibilities include trying to load a disk-cached value
78    /// if possible (incremental only), invoking the query provider if necessary,
79    /// and putting the obtained value into the in-memory cache.
80    ///
81    /// [^1]: [`TyCtxt`], [`crate::query::TyCtxtAt`], [`crate::query::TyCtxtEnsureOk`],
82    /// [`crate::query::TyCtxtEnsureDone`]
83    pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
84}
85
86impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> {
87    pub fn will_cache_on_disk_for_key(&self, key: C::Key) -> bool {
88        self.cache_on_disk_local && (!self.separate_provide_extern || key.as_local_key().is_some())
89    }
90}
91
92impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        // When debug-printing a query vtable (e.g. for ICE or tracing),
95        // just print the query name to know what query we're dealing with.
96        // The other fields and flags are probably just unhelpful noise.
97        //
98        // If there is need for a more detailed dump of all flags and fields,
99        // consider writing a separate dump method and calling it explicitly.
100        f.write_str(self.name)
101    }
102}
103
104pub struct QuerySystem<'tcx> {
105    pub arenas: WorkerLocal<QueryArenas<'tcx>>,
106    pub dep_kind_vtables: &'tcx [DepKindVTable<'tcx>],
107    pub query_vtables: QueryVTables<'tcx>,
108
109    /// Side-effect associated with each [`DepKind::SideEffect`] node in the
110    /// current incremental-compilation session. Side effects will be written
111    /// to disk, and loaded by [`OnDiskCache`] in the next session.
112    ///
113    /// Always empty if incremental compilation is off.
114    pub side_effects: Lock<FxIndexMap<DepNodeIndex, QuerySideEffect>>,
115
116    /// Enabled features that are used in the current compilation.
117    ///
118    /// The value is the `DepNodeIndex` of the node that encodes the used feature.
119    pub used_features: Lock<FxHashMap<Symbol, DepNodeIndex>>,
120
121    /// This provides access to the incremental compilation on-disk cache for query results.
122    /// Do not access this directly. It is only meant to be used by
123    /// `DepGraph::try_mark_green()` and the query infrastructure.
124    /// This is `None` if we are not incremental compilation mode
125    pub on_disk_cache: Option<OnDiskCache>,
126
127    pub local_providers: Providers,
128    pub extern_providers: ExternProviders,
129
130    pub jobs: AtomicU64,
131
132    pub cycle_handler_nesting: Lock<u8>,
133}