Skip to main content

rustc_middle/query/
job.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3use std::num::NonZero;
4use std::sync::Arc;
5
6use parking_lot::{Condvar, Mutex};
7use rustc_data_structures::hash_table::HashTable;
8use rustc_data_structures::sharded::Sharded;
9use rustc_span::Span;
10
11use crate::queries::TaggedQueryKey;
12
13/// A value uniquely identifying an active query job.
14#[derive(#[automatically_derived]
impl ::core::marker::Copy for QueryJobId { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for QueryJobId { }
#[automatically_derived]
impl ::core::clone::Clone for QueryJobId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<NonZero<u64>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for QueryJobId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonZero<u64>>;
    }
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for QueryJobId { }
#[automatically_derived]
impl ::core::cmp::PartialEq for QueryJobId {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for QueryJobId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for QueryJobId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "QueryJobId",
            &&self.0)
    }
}Debug)]
15pub struct QueryJobId(pub NonZero<u64>);
16
17/// Represents an active query job.
18#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for QueryJob<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            id: ::core::clone::Clone::clone(&self.id),
            span: ::core::clone::Clone::clone(&self.span),
            parent: ::core::clone::Clone::clone(&self.parent),
            latch: ::core::clone::Clone::clone(&self.latch),
        }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for QueryJob<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "QueryJob",
            "id", &self.id, "span", &self.span, "parent", &self.parent,
            "latch", &&self.latch)
    }
}Debug)]
19pub struct QueryJob<'tcx> {
20    pub id: QueryJobId,
21
22    /// The span corresponding to the reason for which this query was required.
23    pub span: Span,
24
25    /// The parent query job which created this job and is implicitly waiting on it.
26    pub parent: Option<QueryJobId>,
27
28    /// The latch that is used to wait on this job.
29    pub latch: Option<QueryLatch<'tcx>>,
30}
31
32impl<'tcx> QueryJob<'tcx> {
33    /// Creates a new query job.
34    #[inline]
35    pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
36        QueryJob { id, span, parent, latch: None }
37    }
38}
39
40/// For a particular query and key, tracks the status of a query evaluation
41/// that has started, but has not yet finished successfully.
42///
43/// (Successful query evaluation for a key is represented by an entry in the
44/// query's in-memory cache.)
45pub enum ActiveKeyStatus<'tcx> {
46    /// Some thread is already evaluating the query for this key.
47    ///
48    /// The enclosed [`QueryJob`] can be used to wait for it to finish.
49    Started(QueryJob<'tcx>),
50
51    /// The query panicked. Queries trying to wait on this will raise a fatal error which will
52    /// silently panic.
53    Poisoned,
54}
55
56/// For a particular query, keeps track of "active" keys, i.e. keys whose
57/// evaluation has started but has not yet finished successfully.
58///
59/// (Successful query evaluation for a key is represented by an entry in the
60/// query's in-memory cache.)
61pub struct QueryState<'tcx, K> {
62    pub active: Sharded<HashTable<(K, ActiveKeyStatus<'tcx>)>>,
63}
64
65impl<'tcx, K> Default for QueryState<'tcx, K> {
66    fn default() -> QueryState<'tcx, K> {
67        QueryState { active: Default::default() }
68    }
69}
70
71/// Description of a frame in the query stack.
72///
73/// This is mostly used in case of cycles for error reporting.
74#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for QueryStackFrame<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "QueryStackFrame", "span", &self.span, "tagged_key",
            &&self.tagged_key)
    }
}Debug)]
75pub struct QueryStackFrame<'tcx> {
76    pub span: Span,
77
78    /// The query and key of the query method call that this stack frame
79    /// corresponds to.
80    ///
81    /// Code that doesn't care about the specific key can still use this to
82    /// check which query it's for, or obtain the query's name.
83    pub tagged_key: TaggedQueryKey<'tcx>,
84}
85
86#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for QueryCycle<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "QueryCycle",
            "usage", &self.usage, "frames", &&self.frames)
    }
}Debug)]
87pub struct QueryCycle<'tcx> {
88    /// The query and related span that uses the cycle.
89    pub usage: Option<QueryStackFrame<'tcx>>,
90
91    /// The span here corresponds to the reason for which this query was required.
92    pub frames: Vec<QueryStackFrame<'tcx>>,
93}
94
95#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for QueryWaiter<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "QueryWaiter",
            "parent", &self.parent, "condvar", &self.condvar, "span",
            &self.span, "cycle", &&self.cycle)
    }
}Debug)]
96pub struct QueryWaiter<'tcx> {
97    pub parent: Option<QueryJobId>,
98    pub condvar: Condvar,
99    pub span: Span,
100    pub cycle: Mutex<Option<QueryCycle<'tcx>>>,
101}
102
103#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for QueryLatch<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        Self { waiters: ::core::clone::Clone::clone(&self.waiters) }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for QueryLatch<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "QueryLatch",
            "waiters", &&self.waiters)
    }
}Debug)]
104pub struct QueryLatch<'tcx> {
105    /// The `Option` is `Some(..)` when the job is active, and `None` once completed.
106    pub waiters: Arc<Mutex<Option<Vec<Arc<QueryWaiter<'tcx>>>>>>,
107}
108
109impl<'tcx> QueryLatch<'tcx> {
110    pub fn new() -> Self {
111        QueryLatch { waiters: Arc::new(Mutex::new(Some(Vec::new()))) }
112    }
113}