rustc_query_system/query/
mod.rs1mod plumbing;
2use std::fmt::Debug;
3use std::marker::PhantomData;
4use std::mem::transmute;
5use std::sync::Arc;
6
7pub use self::plumbing::*;
8
9mod job;
10pub use self::job::{
11 QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, break_query_cycles, print_query_stack,
12 report_cycle,
13};
14
15mod caches;
16pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
17
18mod config;
19use rustc_data_structures::sync::{DynSend, DynSync};
20use rustc_errors::DiagInner;
21use rustc_hashes::Hash64;
22use rustc_hir::def::DefKind;
23use rustc_macros::{Decodable, Encodable};
24use rustc_span::Span;
25use rustc_span::def_id::DefId;
26
27pub use self::config::{HashResult, QueryConfig};
28use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
29
30#[derive(Clone, Debug)]
34pub struct QueryStackFrame<I> {
35 pub info: I,
40
41 pub dep_kind: DepKind,
42 hash: Hash64,
45 pub def_id: Option<DefId>,
46 pub def_id_for_ty_in_cycle: Option<DefId>,
48}
49
50impl<I> QueryStackFrame<I> {
51 #[inline]
52 pub fn new(
53 info: I,
54 dep_kind: DepKind,
55 hash: impl FnOnce() -> Hash64,
56 def_id: Option<DefId>,
57 def_id_for_ty_in_cycle: Option<DefId>,
58 ) -> Self {
59 Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle }
60 }
61
62 fn lift<Qcx: QueryContext<QueryInfo = I>>(
63 &self,
64 qcx: Qcx,
65 ) -> QueryStackFrame<QueryStackFrameExtra> {
66 QueryStackFrame {
67 info: qcx.lift_query_info(&self.info),
68 dep_kind: self.dep_kind,
69 hash: self.hash,
70 def_id: self.def_id,
71 def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
72 }
73 }
74}
75
76#[derive(Clone, Debug)]
77pub struct QueryStackFrameExtra {
78 pub description: String,
79 span: Option<Span>,
80 pub def_kind: Option<DefKind>,
81}
82
83impl QueryStackFrameExtra {
84 #[inline]
85 pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
86 Self { description, span, def_kind }
87 }
88
89 #[inline]
91 pub fn default_span(&self, span: Span) -> Span {
92 if !span.is_dummy() {
93 return span;
94 }
95 self.span.unwrap_or(span)
96 }
97}
98
99#[derive(Clone)]
102pub struct QueryStackDeferred<'tcx> {
103 _dummy: PhantomData<&'tcx ()>,
104
105 extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
108}
109
110impl<'tcx> QueryStackDeferred<'tcx> {
111 pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
112 context: C,
113 extract: fn(C) -> QueryStackFrameExtra,
114 ) -> Self {
115 let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
116 Arc::new(move || extract(context));
117 Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
120 }
121
122 pub fn extract(&self) -> QueryStackFrameExtra {
123 (self.extract)()
124 }
125}
126
127impl<'tcx> Debug for QueryStackDeferred<'tcx> {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 f.write_str("QueryStackDeferred")
130 }
131}
132
133#[derive(Debug, Encodable, Decodable)]
143pub enum QuerySideEffect {
144 Diagnostic(DiagInner),
149}
150
151pub trait QueryContext: HasDepContext {
152 type QueryInfo: Clone;
153
154 fn next_job_id(self) -> QueryJobId;
155
156 fn current_query_job(self) -> Option<QueryJobId>;
158
159 fn collect_active_jobs(self) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;
160
161 fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra;
162
163 fn load_side_effect(
165 self,
166 prev_dep_node_index: SerializedDepNodeIndex,
167 ) -> Option<QuerySideEffect>;
168
169 fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect);
171
172 fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R)
175 -> R;
176
177 fn depth_limit_error(self, job: QueryJobId);
178}