rustc_query_system/query/
mod.rs

1use rustc_data_structures::jobserver::Proxy;
2use rustc_errors::DiagInner;
3use rustc_hashes::Hash64;
4use rustc_hir::def::DefKind;
5use rustc_macros::{Decodable, Encodable};
6use rustc_span::Span;
7use rustc_span::def_id::DefId;
8
9pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
10pub use self::config::{HashResult, QueryConfig};
11pub use self::job::{
12    QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, break_query_cycles, print_query_stack,
13    report_cycle,
14};
15pub use self::plumbing::*;
16use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
17
18mod caches;
19mod config;
20mod job;
21mod plumbing;
22
23/// Description of a frame in the query stack.
24///
25/// This is mostly used in case of cycles for error reporting.
26#[derive(#[automatically_derived]
impl ::core::clone::Clone for QueryStackFrame {
    #[inline]
    fn clone(&self) -> QueryStackFrame {
        QueryStackFrame {
            description: ::core::clone::Clone::clone(&self.description),
            span: ::core::clone::Clone::clone(&self.span),
            def_id: ::core::clone::Clone::clone(&self.def_id),
            def_kind: ::core::clone::Clone::clone(&self.def_kind),
            def_id_for_ty_in_cycle: ::core::clone::Clone::clone(&self.def_id_for_ty_in_cycle),
            dep_kind: ::core::clone::Clone::clone(&self.dep_kind),
            hash: ::core::clone::Clone::clone(&self.hash),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for QueryStackFrame {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["description", "span", "def_id", "def_kind",
                        "def_id_for_ty_in_cycle", "dep_kind", "hash"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.description, &self.span, &self.def_id, &self.def_kind,
                        &self.def_id_for_ty_in_cycle, &self.dep_kind, &&self.hash];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "QueryStackFrame", names, values)
    }
}Debug)]
27pub struct QueryStackFrame {
28    pub description: String,
29    span: Option<Span>,
30    pub def_id: Option<DefId>,
31    pub def_kind: Option<DefKind>,
32    /// A def-id that is extracted from a `Ty` in a query key
33    pub def_id_for_ty_in_cycle: Option<DefId>,
34    pub dep_kind: DepKind,
35    /// This hash is used to deterministically pick
36    /// a query to remove cycles in the parallel compiler.
37    hash: Hash64,
38}
39
40impl QueryStackFrame {
41    #[inline]
42    pub fn new(
43        description: String,
44        span: Option<Span>,
45        def_id: Option<DefId>,
46        def_kind: Option<DefKind>,
47        dep_kind: DepKind,
48        def_id_for_ty_in_cycle: Option<DefId>,
49        hash: Hash64,
50    ) -> Self {
51        Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash }
52    }
53
54    // FIXME(eddyb) Get more valid `Span`s on queries.
55    #[inline]
56    pub fn default_span(&self, span: Span) -> Span {
57        if !span.is_dummy() {
58            return span;
59        }
60        self.span.unwrap_or(span)
61    }
62}
63
64/// Tracks 'side effects' for a particular query.
65/// This struct is saved to disk along with the query result,
66/// and loaded from disk if we mark the query as green.
67/// This allows us to 'replay' changes to global state
68/// that would otherwise only occur if we actually
69/// executed the query method.
70///
71/// Each side effect gets an unique dep node index which is added
72/// as a dependency of the query which had the effect.
73#[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)]
74pub enum QuerySideEffect {
75    /// Stores a diagnostic emitted during query execution.
76    /// This diagnostic will be re-emitted if we mark
77    /// the query as green, as that query will have the side
78    /// effect dep node as a dependency.
79    Diagnostic(DiagInner),
80}
81
82pub trait QueryContext: HasDepContext {
83    /// Gets a jobserver reference which is used to release then acquire
84    /// a token while waiting on a query.
85    fn jobserver_proxy(&self) -> &Proxy;
86
87    fn next_job_id(self) -> QueryJobId;
88
89    /// Get the query information from the TLS context.
90    fn current_query_job(self) -> Option<QueryJobId>;
91
92    fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap, QueryMap>;
93
94    /// Load a side effect associated to the node in the previous session.
95    fn load_side_effect(
96        self,
97        prev_dep_node_index: SerializedDepNodeIndex,
98    ) -> Option<QuerySideEffect>;
99
100    /// Register a side effect for the given node, for use in next session.
101    fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect);
102
103    /// Executes a job by changing the `ImplicitCtxt` to point to the
104    /// new query job while it executes.
105    fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R)
106    -> R;
107
108    fn depth_limit_error(self, job: QueryJobId);
109}