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(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}