1use std::fmt::Debug;
2use std::marker::PhantomData;
3use std::mem::transmute;
4use std::sync::Arc;
56use rustc_data_structures::jobserver::Proxy;
7use rustc_data_structures::sync::{DynSend, DynSync};
8use rustc_errors::DiagInner;
9use rustc_hashes::Hash64;
10use rustc_hir::def::DefKind;
11use rustc_macros::{Decodable, Encodable};
12use rustc_span::Span;
13use rustc_span::def_id::DefId;
1415pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
16pub use self::dispatcher::{HashResult, QueryDispatcher};
17pub use self::job::{
18QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, break_query_cycles, print_query_stack,
19report_cycle,
20};
21pub use self::plumbing::*;
22use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
2324mod caches;
25mod dispatcher;
26mod job;
27mod plumbing;
2829/// How a particular query deals with query cycle errors.
30///
31/// Inspected by the code that actually handles cycle errors, to decide what
32/// approach to use.
33#[derive(#[automatically_derived]
impl ::core::marker::Copy for CycleErrorHandling { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CycleErrorHandling {
#[inline]
fn clone(&self) -> CycleErrorHandling { *self }
}Clone)]
34pub enum CycleErrorHandling {
35 Error,
36 Fatal,
37 DelayBug,
38 Stash,
39}
4041/// Description of a frame in the query stack.
42///
43/// This is mostly used in case of cycles for error reporting.
44#[derive(#[automatically_derived]
impl<I: ::core::clone::Clone> ::core::clone::Clone for QueryStackFrame<I> {
#[inline]
fn clone(&self) -> QueryStackFrame<I> {
QueryStackFrame {
info: ::core::clone::Clone::clone(&self.info),
dep_kind: ::core::clone::Clone::clone(&self.dep_kind),
hash: ::core::clone::Clone::clone(&self.hash),
def_id: ::core::clone::Clone::clone(&self.def_id),
def_id_for_ty_in_cycle: ::core::clone::Clone::clone(&self.def_id_for_ty_in_cycle),
}
}
}Clone, #[automatically_derived]
impl<I: ::core::fmt::Debug> ::core::fmt::Debug for QueryStackFrame<I> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"QueryStackFrame", "info", &self.info, "dep_kind", &self.dep_kind,
"hash", &self.hash, "def_id", &self.def_id,
"def_id_for_ty_in_cycle", &&self.def_id_for_ty_in_cycle)
}
}Debug)]
45pub struct QueryStackFrame<I> {
46/// This field initially stores a `QueryStackDeferred` during collection,
47 /// but can later be changed to `QueryStackFrameExtra` containing concrete information
48 /// by calling `lift`. This is done so that collecting query does not need to invoke
49 /// queries, instead `lift` will call queries in a more appropriate location.
50pub info: I,
5152pub dep_kind: DepKind,
53/// This hash is used to deterministically pick
54 /// a query to remove cycles in the parallel compiler.
55hash: Hash64,
56pub def_id: Option<DefId>,
57/// A def-id that is extracted from a `Ty` in a query key
58pub def_id_for_ty_in_cycle: Option<DefId>,
59}
6061impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
62#[inline]
63pub fn new(
64 info: QueryStackDeferred<'tcx>,
65 dep_kind: DepKind,
66 hash: Hash64,
67 def_id: Option<DefId>,
68 def_id_for_ty_in_cycle: Option<DefId>,
69 ) -> Self {
70Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle }
71 }
7273fn lift<Qcx: QueryContext<'tcx>>(&self, qcx: Qcx) -> QueryStackFrame<QueryStackFrameExtra> {
74QueryStackFrame {
75 info: qcx.lift_query_info(&self.info),
76 dep_kind: self.dep_kind,
77 hash: self.hash,
78 def_id: self.def_id,
79 def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
80 }
81 }
82}
8384#[derive(#[automatically_derived]
impl ::core::clone::Clone for QueryStackFrameExtra {
#[inline]
fn clone(&self) -> QueryStackFrameExtra {
QueryStackFrameExtra {
description: ::core::clone::Clone::clone(&self.description),
span: ::core::clone::Clone::clone(&self.span),
def_kind: ::core::clone::Clone::clone(&self.def_kind),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for QueryStackFrameExtra {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"QueryStackFrameExtra", "description", &self.description, "span",
&self.span, "def_kind", &&self.def_kind)
}
}Debug)]
85pub struct QueryStackFrameExtra {
86pub description: String,
87 span: Option<Span>,
88pub def_kind: Option<DefKind>,
89}
9091impl QueryStackFrameExtra {
92#[inline]
93pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
94Self { description, span, def_kind }
95 }
9697// FIXME(eddyb) Get more valid `Span`s on queries.
98#[inline]
99pub fn default_span(&self, span: Span) -> Span {
100if !span.is_dummy() {
101return span;
102 }
103self.span.unwrap_or(span)
104 }
105}
106107/// Track a 'side effect' for a particular query.
108/// This is used to hold a closure which can create `QueryStackFrameExtra`.
109#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for QueryStackDeferred<'tcx> {
#[inline]
fn clone(&self) -> QueryStackDeferred<'tcx> {
QueryStackDeferred {
_dummy: ::core::clone::Clone::clone(&self._dummy),
extract: ::core::clone::Clone::clone(&self.extract),
}
}
}Clone)]
110pub struct QueryStackDeferred<'tcx> {
111 _dummy: PhantomData<&'tcx ()>,
112113// `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
114 // access it in the destructor.
115extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
116}
117118impl<'tcx> QueryStackDeferred<'tcx> {
119pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
120 context: C,
121 extract: fn(C) -> QueryStackFrameExtra,
122 ) -> Self {
123let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
124Arc::new(move || extract(context));
125// SAFETY: The `extract` closure does not access 'tcx in its destructor as the only
126 // captured variable is `context` which is Copy and cannot have a destructor.
127Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
128 }
129130pub fn extract(&self) -> QueryStackFrameExtra {
131 (self.extract)()
132 }
133}
134135impl<'tcx> Debugfor QueryStackDeferred<'tcx> {
136fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137f.write_str("QueryStackDeferred")
138 }
139}
140141/// Tracks 'side effects' for a particular query.
142/// This struct is saved to disk along with the query result,
143/// and loaded from disk if we mark the query as green.
144/// This allows us to 'replay' changes to global state
145/// that would otherwise only occur if we actually
146/// executed the query method.
147///
148/// Each side effect gets an unique dep node index which is added
149/// as a dependency of the query which had the effect.
150#[derive(#[automatically_derived]
impl ::core::fmt::Debug for QuerySideEffect {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
QuerySideEffect::Diagnostic(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Diagnostic", &__self_0),
}
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for QuerySideEffect {
fn encode(&self, __encoder: &mut __E) {
match *self {
QuerySideEffect::Diagnostic(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for QuerySideEffect {
fn decode(__decoder: &mut __D) -> Self {
QuerySideEffect::Diagnostic(::rustc_serialize::Decodable::decode(__decoder))
}
}
};Decodable)]
151pub enum QuerySideEffect {
152/// Stores a diagnostic emitted during query execution.
153 /// This diagnostic will be re-emitted if we mark
154 /// the query as green, as that query will have the side
155 /// effect dep node as a dependency.
156Diagnostic(DiagInner),
157}
158159pub trait QueryContext<'tcx>: HasDepContext {
160/// Gets a jobserver reference which is used to release then acquire
161 /// a token while waiting on a query.
162fn jobserver_proxy(&self) -> &Proxy;
163164fn next_job_id(self) -> QueryJobId;
165166/// Get the query information from the TLS context.
167fn current_query_job(self) -> Option<QueryJobId>;
168169fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap<'tcx>, QueryMap<'tcx>>;
170171fn lift_query_info(self, info: &QueryStackDeferred<'tcx>) -> QueryStackFrameExtra;
172173/// Load a side effect associated to the node in the previous session.
174fn load_side_effect(
175self,
176 prev_dep_node_index: SerializedDepNodeIndex,
177 ) -> Option<QuerySideEffect>;
178179/// Register a side effect for the given node, for use in next session.
180fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect);
181182/// Executes a job by changing the `ImplicitCtxt` to point to the
183 /// new query job while it executes.
184fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R)
185 -> R;
186187fn depth_limit_error(self, job: QueryJobId);
188}