1use std::fmt::Debug;
2use std::hash::Hash;
3use std::num::NonZero;
4use std::sync::Arc;
5
6use parking_lot::{Condvar, Mutex};
7use rustc_span::Span;
8
9use crate::query::plumbing::CycleError;
10use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
11use crate::ty::TyCtxt;
12
13#[derive(#[automatically_derived]
impl<I: ::core::clone::Clone> ::core::clone::Clone for QueryInfo<I> {
#[inline]
fn clone(&self) -> QueryInfo<I> {
QueryInfo {
span: ::core::clone::Clone::clone(&self.span),
frame: ::core::clone::Clone::clone(&self.frame),
}
}
}Clone, #[automatically_derived]
impl<I: ::core::fmt::Debug> ::core::fmt::Debug for QueryInfo<I> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "QueryInfo",
"span", &self.span, "frame", &&self.frame)
}
}Debug)]
15pub struct QueryInfo<I> {
16 pub span: Span,
18 pub frame: QueryStackFrame<I>,
19}
20
21impl<'tcx> QueryInfo<QueryStackDeferred<'tcx>> {
22 pub(crate) fn lift(&self) -> QueryInfo<QueryStackFrameExtra> {
23 QueryInfo { span: self.span, frame: self.frame.lift() }
24 }
25}
26
27#[derive(#[automatically_derived]
impl ::core::marker::Copy for QueryJobId { }Copy, #[automatically_derived]
impl ::core::clone::Clone for QueryJobId {
#[inline]
fn clone(&self) -> QueryJobId {
let _: ::core::clone::AssertParamIsClone<NonZero<u64>>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for QueryJobId {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<NonZero<u64>>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for QueryJobId {
#[inline]
fn eq(&self, other: &QueryJobId) -> 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)]
29pub struct QueryJobId(pub NonZero<u64>);
30
31#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for QueryJob<'tcx> {
#[inline]
fn clone(&self) -> QueryJob<'tcx> {
QueryJob {
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)]
33pub struct QueryJob<'tcx> {
34 pub id: QueryJobId,
35
36 pub span: Span,
38
39 pub parent: Option<QueryJobId>,
41
42 pub latch: Option<QueryLatch<'tcx>>,
44}
45
46impl<'tcx> QueryJob<'tcx> {
47 #[inline]
49 pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
50 QueryJob { id, span, parent, latch: None }
51 }
52
53 pub fn latch(&mut self) -> QueryLatch<'tcx> {
54 if self.latch.is_none() {
55 self.latch = Some(QueryLatch::new());
56 }
57 self.latch.as_ref().unwrap().clone()
58 }
59
60 #[inline]
65 pub fn signal_complete(self) {
66 if let Some(latch) = self.latch {
67 latch.set();
68 }
69 }
70}
71
72#[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",
"query", &self.query, "condvar", &self.condvar, "span",
&self.span, "cycle", &&self.cycle)
}
}Debug)]
73pub struct QueryWaiter<'tcx> {
74 pub query: Option<QueryJobId>,
75 pub condvar: Condvar,
76 pub span: Span,
77 pub cycle: Mutex<Option<CycleError<QueryStackDeferred<'tcx>>>>,
78}
79
80#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for QueryLatchInfo<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"QueryLatchInfo", "complete", &self.complete, "waiters",
&&self.waiters)
}
}Debug)]
81pub struct QueryLatchInfo<'tcx> {
82 pub complete: bool,
83 pub waiters: Vec<Arc<QueryWaiter<'tcx>>>,
84}
85
86#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for QueryLatch<'tcx> {
#[inline]
fn clone(&self) -> QueryLatch<'tcx> {
QueryLatch { info: ::core::clone::Clone::clone(&self.info) }
}
}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",
"info", &&self.info)
}
}Debug)]
87pub struct QueryLatch<'tcx> {
88 pub info: Arc<Mutex<QueryLatchInfo<'tcx>>>,
89}
90
91impl<'tcx> QueryLatch<'tcx> {
92 fn new() -> Self {
93 QueryLatch {
94 info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })),
95 }
96 }
97
98 pub fn wait_on(
100 &self,
101 tcx: TyCtxt<'tcx>,
102 query: Option<QueryJobId>,
103 span: Span,
104 ) -> Result<(), CycleError<QueryStackDeferred<'tcx>>> {
105 let waiter =
106 Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
107 self.wait_on_inner(tcx, &waiter);
108 let mut cycle = waiter.cycle.lock();
112 match cycle.take() {
113 None => Ok(()),
114 Some(cycle) => Err(cycle),
115 }
116 }
117
118 fn wait_on_inner(&self, tcx: TyCtxt<'tcx>, waiter: &Arc<QueryWaiter<'tcx>>) {
120 let mut info = self.info.lock();
121 if !info.complete {
122 info.waiters.push(Arc::clone(waiter));
127
128 rustc_thread_pool::mark_blocked();
132 tcx.jobserver_proxy.release_thread();
133 waiter.condvar.wait(&mut info);
134 drop(info);
136 tcx.jobserver_proxy.acquire_thread();
137 }
138 }
139
140 fn set(&self) {
142 let mut info = self.info.lock();
143 if true {
if !!info.complete {
::core::panicking::panic("assertion failed: !info.complete")
};
};debug_assert!(!info.complete);
144 info.complete = true;
145 let registry = rustc_thread_pool::Registry::current();
146 for waiter in info.waiters.drain(..) {
147 rustc_thread_pool::mark_unblocked(®istry);
148 waiter.condvar.notify_one();
149 }
150 }
151
152 pub fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter<'tcx>> {
155 let mut info = self.info.lock();
156 if true {
if !!info.complete {
::core::panicking::panic("assertion failed: !info.complete")
};
};debug_assert!(!info.complete);
157 info.waiters.remove(waiter)
159 }
160}