Skip to main content

rustc_query_system/query/
mod.rs

1use std::fmt::Debug;
2use std::marker::PhantomData;
3use std::mem::transmute;
4use std::sync::Arc;
5
6use 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;
14
15pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
16pub use self::dispatcher::{HashResult, QueryDispatcher};
17pub use self::job::{
18    QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, break_query_cycles, print_query_stack,
19    report_cycle,
20};
21pub use self::plumbing::*;
22use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
23
24mod caches;
25mod dispatcher;
26mod job;
27mod plumbing;
28
29/// 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}
40
41/// 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.
50    pub info: I,
51
52    pub dep_kind: DepKind,
53    /// This hash is used to deterministically pick
54    /// a query to remove cycles in the parallel compiler.
55    hash: Hash64,
56    pub def_id: Option<DefId>,
57    /// A def-id that is extracted from a `Ty` in a query key
58    pub def_id_for_ty_in_cycle: Option<DefId>,
59}
60
61impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
62    #[inline]
63    pub 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 {
70        Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle }
71    }
72
73    fn lift<Qcx: QueryContext<'tcx>>(&self, qcx: Qcx) -> QueryStackFrame<QueryStackFrameExtra> {
74        QueryStackFrame {
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}
83
84#[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 {
86    pub description: String,
87    span: Option<Span>,
88    pub def_kind: Option<DefKind>,
89}
90
91impl QueryStackFrameExtra {
92    #[inline]
93    pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
94        Self { description, span, def_kind }
95    }
96
97    // FIXME(eddyb) Get more valid `Span`s on queries.
98    #[inline]
99    pub fn default_span(&self, span: Span) -> Span {
100        if !span.is_dummy() {
101            return span;
102        }
103        self.span.unwrap_or(span)
104    }
105}
106
107/// 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 ()>,
112
113    // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
114    // access it in the destructor.
115    extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
116}
117
118impl<'tcx> QueryStackDeferred<'tcx> {
119    pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
120        context: C,
121        extract: fn(C) -> QueryStackFrameExtra,
122    ) -> Self {
123        let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
124            Arc::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.
127        Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
128    }
129
130    pub fn extract(&self) -> QueryStackFrameExtra {
131        (self.extract)()
132    }
133}
134
135impl<'tcx> Debug for QueryStackDeferred<'tcx> {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        f.write_str("QueryStackDeferred")
138    }
139}
140
141/// 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.
156    Diagnostic(DiagInner),
157}
158
159pub trait QueryContext<'tcx>: HasDepContext {
160    /// Gets a jobserver reference which is used to release then acquire
161    /// a token while waiting on a query.
162    fn jobserver_proxy(&self) -> &Proxy;
163
164    fn next_job_id(self) -> QueryJobId;
165
166    /// Get the query information from the TLS context.
167    fn current_query_job(self) -> Option<QueryJobId>;
168
169    fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap<'tcx>, QueryMap<'tcx>>;
170
171    fn lift_query_info(self, info: &QueryStackDeferred<'tcx>) -> QueryStackFrameExtra;
172
173    /// Load a side effect associated to the node in the previous session.
174    fn load_side_effect(
175        self,
176        prev_dep_node_index: SerializedDepNodeIndex,
177    ) -> Option<QuerySideEffect>;
178
179    /// Register a side effect for the given node, for use in next session.
180    fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect);
181
182    /// Executes a job by changing the `ImplicitCtxt` to point to the
183    /// new query job while it executes.
184    fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R)
185    -> R;
186
187    fn depth_limit_error(self, job: QueryJobId);
188}