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::jobserver::Proxy;
20use rustc_data_structures::sync::{DynSend, DynSync};
21use rustc_errors::DiagInner;
22use rustc_hashes::Hash64;
23use rustc_hir::def::DefKind;
24use rustc_macros::{Decodable, Encodable};
25use rustc_span::Span;
26use rustc_span::def_id::DefId;
27
28pub use self::config::{HashResult, QueryConfig};
29use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
30
31#[derive(Clone, Debug)]
35pub struct QueryStackFrame<I> {
36 pub info: I,
41
42 pub dep_kind: DepKind,
43 hash: Hash64,
46 pub def_id: Option<DefId>,
47 pub def_id_for_ty_in_cycle: Option<DefId>,
49}
50
51impl<I> QueryStackFrame<I> {
52 #[inline]
53 pub fn new(
54 info: I,
55 dep_kind: DepKind,
56 hash: impl FnOnce() -> Hash64,
57 def_id: Option<DefId>,
58 def_id_for_ty_in_cycle: Option<DefId>,
59 ) -> Self {
60 Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle }
61 }
62
63 fn lift<Qcx: QueryContext<QueryInfo = I>>(
64 &self,
65 qcx: Qcx,
66 ) -> QueryStackFrame<QueryStackFrameExtra> {
67 QueryStackFrame {
68 info: qcx.lift_query_info(&self.info),
69 dep_kind: self.dep_kind,
70 hash: self.hash,
71 def_id: self.def_id,
72 def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
73 }
74 }
75}
76
77#[derive(Clone, Debug)]
78pub struct QueryStackFrameExtra {
79 pub description: String,
80 span: Option<Span>,
81 pub def_kind: Option<DefKind>,
82}
83
84impl QueryStackFrameExtra {
85 #[inline]
86 pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
87 Self { description, span, def_kind }
88 }
89
90 #[inline]
92 pub fn default_span(&self, span: Span) -> Span {
93 if !span.is_dummy() {
94 return span;
95 }
96 self.span.unwrap_or(span)
97 }
98}
99
100#[derive(Clone)]
103pub struct QueryStackDeferred<'tcx> {
104 _dummy: PhantomData<&'tcx ()>,
105
106 extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
109}
110
111impl<'tcx> QueryStackDeferred<'tcx> {
112 pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
113 context: C,
114 extract: fn(C) -> QueryStackFrameExtra,
115 ) -> Self {
116 let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
117 Arc::new(move || extract(context));
118 Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
121 }
122
123 pub fn extract(&self) -> QueryStackFrameExtra {
124 (self.extract)()
125 }
126}
127
128impl<'tcx> Debug for QueryStackDeferred<'tcx> {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 f.write_str("QueryStackDeferred")
131 }
132}
133
134#[derive(Debug, Encodable, Decodable)]
144pub enum QuerySideEffect {
145 Diagnostic(DiagInner),
150}
151
152pub trait QueryContext: HasDepContext {
153 type QueryInfo: Clone;
154
155 fn jobserver_proxy(&self) -> &Proxy;
158
159 fn next_job_id(self) -> QueryJobId;
160
161 fn current_query_job(self) -> Option<QueryJobId>;
163
164 fn collect_active_jobs(self) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;
165
166 fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra;
167
168 fn load_side_effect(
170 self,
171 prev_dep_node_index: SerializedDepNodeIndex,
172 ) -> Option<QuerySideEffect>;
173
174 fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect);
176
177 fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R)
180 -> R;
181
182 fn depth_limit_error(self, job: QueryJobId);
183}