Skip to main content

rustc_query_system/query/
dispatcher.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3
4use rustc_data_structures::fingerprint::Fingerprint;
5use rustc_span::ErrorGuaranteed;
6
7use super::QueryStackFrameExtra;
8use crate::dep_graph::{DepKind, DepNode, DepNodeParams, HasDepContext, SerializedDepNodeIndex};
9use crate::ich::StableHashingContext;
10use crate::query::caches::QueryCache;
11use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState};
12
13pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
14
15/// Unambiguous shorthand for `<This::Qcx as HasDepContext>::DepContext`.
16#[expect(type_alias_bounds)]
17type DepContextOf<'tcx, This: QueryDispatcher<'tcx>> =
18    <<This as QueryDispatcher<'tcx>>::Qcx as HasDepContext>::DepContext;
19
20/// Trait that can be used as a vtable for a single query, providing operations
21/// and metadata for that query.
22///
23/// Implemented by `rustc_query_impl::SemiDynamicQueryDispatcher`, which
24/// mostly delegates to `rustc_middle::query::plumbing::QueryVTable`.
25/// Those types are not visible from this `rustc_query_system` crate.
26///
27/// "Dispatcher" should be understood as a near-synonym of "vtable".
28pub trait QueryDispatcher<'tcx>: Copy {
29    fn name(self) -> &'static str;
30
31    /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`.
32    type Qcx: QueryContext<'tcx>;
33
34    // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
35    // but it isn't necessary.
36    type Key: DepNodeParams<DepContextOf<'tcx, Self>> + Eq + Hash + Copy + Debug;
37    type Value: Copy;
38
39    type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
40
41    fn format_value(self) -> fn(&Self::Value) -> String;
42
43    // Don't use this method to access query results, instead use the methods on TyCtxt
44    fn query_state<'a>(self, tcx: Self::Qcx) -> &'a QueryState<'tcx, Self::Key>;
45
46    // Don't use this method to access query results, instead use the methods on TyCtxt
47    fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache;
48
49    fn will_cache_on_disk_for_key(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool;
50
51    // Don't use this method to compute query results, instead use the methods on TyCtxt
52    fn execute_query(self, tcx: DepContextOf<'tcx, Self>, k: Self::Key) -> Self::Value;
53
54    fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value;
55
56    fn try_load_from_disk(
57        self,
58        tcx: Self::Qcx,
59        key: &Self::Key,
60        prev_index: SerializedDepNodeIndex,
61        index: DepNodeIndex,
62    ) -> Option<Self::Value>;
63
64    fn is_loadable_from_disk(
65        self,
66        qcx: Self::Qcx,
67        key: &Self::Key,
68        idx: SerializedDepNodeIndex,
69    ) -> bool;
70
71    /// Synthesize an error value to let compilation continue after a cycle.
72    fn value_from_cycle_error(
73        self,
74        tcx: DepContextOf<'tcx, Self>,
75        cycle_error: &CycleError<QueryStackFrameExtra>,
76        guar: ErrorGuaranteed,
77    ) -> Self::Value;
78
79    fn anon(self) -> bool;
80    fn eval_always(self) -> bool;
81    fn depth_limit(self) -> bool;
82    fn feedable(self) -> bool;
83
84    fn dep_kind(self) -> DepKind;
85    fn cycle_error_handling(self) -> CycleErrorHandling;
86    fn hash_result(self) -> HashResult<Self::Value>;
87
88    // Just here for convenience and checking that the key matches the kind, don't override this.
89    fn construct_dep_node(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> DepNode {
90        DepNode::construct(tcx, self.dep_kind(), key)
91    }
92}