1use std::fmt::Debug;
2use std::hash::Hash;
3use std::num::NonZero;
4use std::sync::Arc;
56use parking_lot::{Condvar, Mutex};
7use rustc_data_structures::hash_table::HashTable;
8use rustc_data_structures::sharded::Sharded;
9use rustc_span::Span;
1011use crate::queries::TaggedQueryKey;
1213/// 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>);
1617/// 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> {
20pub id: QueryJobId,
2122/// The span corresponding to the reason for which this query was required.
23pub span: Span,
2425/// The parent query job which created this job and is implicitly waiting on it.
26pub parent: Option<QueryJobId>,
2728/// The latch that is used to wait on this job.
29pub latch: Option<QueryLatch<'tcx>>,
30}
3132impl<'tcx> QueryJob<'tcx> {
33/// Creates a new query job.
34#[inline]
35pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
36QueryJob { id, span, parent, latch: None }
37 }
38}
3940/// 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.
49Started(QueryJob<'tcx>),
5051/// The query panicked. Queries trying to wait on this will raise a fatal error which will
52 /// silently panic.
53Poisoned,
54}
5556/// 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> {
62pub active: Sharded<HashTable<(K, ActiveKeyStatus<'tcx>)>>,
63}
6465impl<'tcx, K> Defaultfor QueryState<'tcx, K> {
66fn default() -> QueryState<'tcx, K> {
67QueryState { active: Default::default() }
68 }
69}
7071/// 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> {
76pub span: Span,
7778/// 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.
83pub tagged_key: TaggedQueryKey<'tcx>,
84}
8586#[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.
89pub usage: Option<QueryStackFrame<'tcx>>,
9091/// The span here corresponds to the reason for which this query was required.
92pub frames: Vec<QueryStackFrame<'tcx>>,
93}
9495#[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> {
97pub parent: Option<QueryJobId>,
98pub condvar: Condvar,
99pub span: Span,
100pub cycle: Mutex<Option<QueryCycle<'tcx>>>,
101}
102103#[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.
106pub waiters: Arc<Mutex<Option<Vec<Arc<QueryWaiter<'tcx>>>>>>,
107}
108109impl<'tcx> QueryLatch<'tcx> {
110pub fn new() -> Self {
111QueryLatch { waiters: Arc::new(Mutex::new(Some(Vec::new()))) }
112 }
113}