Skip to content

Commit 16c3f08

Browse files
committed
Add a QueryKeyId to identify a query instance
1 parent 69370dc commit 16c3f08

11 files changed

Lines changed: 151 additions & 229 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4458,7 +4458,6 @@ dependencies = [
44584458
"rustc_macros",
44594459
"rustc_middle",
44604460
"rustc_serialize",
4461-
"rustc_session",
44624461
"rustc_span",
44634462
"rustc_thread_pool",
44644463
"tracing",

compiler/rustc_middle/src/query/job.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,15 @@ use parking_lot::{Condvar, Mutex};
77
use rustc_span::Span;
88

99
use crate::query::plumbing::CycleError;
10-
use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
10+
use crate::query::stack::QueryStackFrame;
1111
use crate::ty::TyCtxt;
1212

1313
/// Represents a span and a query key.
1414
#[derive(Clone, Debug)]
15-
pub struct QueryInfo<I> {
15+
pub struct QueryInfo<'tcx> {
1616
/// The span corresponding to the reason for which this query was required.
1717
pub span: Span,
18-
pub frame: QueryStackFrame<I>,
19-
}
20-
21-
impl<'tcx> QueryInfo<QueryStackDeferred<'tcx>> {
22-
pub(crate) fn lift(&self) -> QueryInfo<QueryStackFrameExtra> {
23-
QueryInfo { span: self.span, frame: self.frame.lift() }
24-
}
18+
pub frame: QueryStackFrame<'tcx>,
2519
}
2620

2721
/// A value uniquely identifying an active query job.
@@ -74,7 +68,7 @@ pub struct QueryWaiter<'tcx> {
7468
pub query: Option<QueryJobId>,
7569
pub condvar: Condvar,
7670
pub span: Span,
77-
pub cycle: Mutex<Option<CycleError<QueryStackDeferred<'tcx>>>>,
71+
pub cycle: Mutex<Option<CycleError<'tcx>>>,
7872
}
7973

8074
#[derive(Debug)]
@@ -101,7 +95,7 @@ impl<'tcx> QueryLatch<'tcx> {
10195
tcx: TyCtxt<'tcx>,
10296
query: Option<QueryJobId>,
10397
span: Span,
104-
) -> Result<(), CycleError<QueryStackDeferred<'tcx>>> {
98+
) -> Result<(), CycleError<'tcx>> {
10599
let waiter =
106100
Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
107101
self.wait_on_inner(tcx, &waiter);

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub use self::plumbing::{
77
ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode,
88
QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk,
99
};
10-
pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
10+
pub use self::stack::QueryStackFrame;
1111
pub use crate::queries::Providers;
1212
use crate::ty::TyCtxt;
1313

compiler/rustc_middle/src/query/plumbing.rs

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
1515
use crate::ich::StableHashingContext;
1616
use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables};
1717
use crate::query::on_disk_cache::OnDiskCache;
18-
use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
18+
use crate::query::stack::QueryStackFrame;
1919
use crate::query::{QueryCache, QueryInfo, QueryJob};
2020
use crate::ty::TyCtxt;
2121

@@ -62,19 +62,10 @@ pub enum CycleErrorHandling {
6262
}
6363

6464
#[derive(Clone, Debug)]
65-
pub struct CycleError<I = QueryStackFrameExtra> {
65+
pub struct CycleError<'tcx> {
6666
/// The query and related span that uses the cycle.
67-
pub usage: Option<(Span, QueryStackFrame<I>)>,
68-
pub cycle: Vec<QueryInfo<I>>,
69-
}
70-
71-
impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
72-
pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
73-
CycleError {
74-
usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())),
75-
cycle: self.cycle.iter().map(|info| info.lift()).collect(),
76-
}
77-
}
67+
pub usage: Option<(Span, QueryStackFrame<'tcx>)>,
68+
pub cycle: Vec<QueryInfo<'tcx>>,
7869
}
7970

8071
#[derive(Debug)]
@@ -146,15 +137,9 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
146137
pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
147138

148139
pub value_from_cycle_error:
149-
fn(tcx: TyCtxt<'tcx>, cycle_error: CycleError, guar: ErrorGuaranteed) -> C::Value,
140+
fn(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>, guar: ErrorGuaranteed) -> C::Value,
150141
pub format_value: fn(&C::Value) -> String,
151142

152-
/// Formats a human-readable description of this query and its key, as
153-
/// specified by the `desc` query modifier.
154-
///
155-
/// Used when reporting query cycle errors and similar problems.
156-
pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String,
157-
158143
/// Function pointer that is called by the query methods on [`TyCtxt`] and
159144
/// friends[^1], after they have checked the in-memory cache and found no
160145
/// existing value for this key.
@@ -516,6 +501,67 @@ macro_rules! define_callbacks {
516501
}
517502
)*
518503

504+
/// Identifies a query by kind and key. This is in contrast to `QueryId` which is just a number.
505+
#[allow(non_camel_case_types)]
506+
#[derive(Clone, Debug)]
507+
pub enum QueryKeyId<'tcx> {
508+
$(
509+
$name($name::Key<'tcx>),
510+
)*
511+
}
512+
513+
impl<'tcx> QueryKeyId<'tcx> {
514+
/// Formats a human-readable description of this query and its key, as
515+
/// specified by the `desc` query modifier.
516+
///
517+
/// Used when reporting query cycle errors and similar problems.
518+
pub fn description(&self, tcx: TyCtxt<'tcx>) -> String {
519+
let (name, description) = ty::print::with_no_queries!(match self {
520+
$(
521+
QueryKeyId::$name(key) => (stringify!($name), _description_fns::$name(tcx, *key)),
522+
)*
523+
});
524+
if tcx.sess.verbose_internals() {
525+
format!("{description} [{name:?}]")
526+
} else {
527+
description
528+
}
529+
}
530+
531+
/// Returns the default span for this query if `span` is a dummy span.
532+
pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
533+
if !span.is_dummy() {
534+
return span
535+
}
536+
if let QueryKeyId::def_span(..) = self {
537+
// The `def_span` query is used to calculate `default_span`,
538+
// so exit to avoid infinite recursion.
539+
return DUMMY_SP
540+
}
541+
match self {
542+
$(
543+
QueryKeyId::$name(key) => crate::query::QueryKey::default_span(key, tcx),
544+
)*
545+
}
546+
}
547+
548+
pub fn def_kind(&self, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
549+
fn inner<'tcx>(key: &impl crate::query::QueryKey, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
550+
key.key_as_def_id().and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
551+
}
552+
553+
if let QueryKeyId::def_kind(..) = self {
554+
// Try to avoid infinite recursion.
555+
return None
556+
}
557+
match self {
558+
$(
559+
QueryKeyId::$name(key) => inner(key, tcx),
560+
)*
561+
}
562+
}
563+
}
564+
519565
/// Holds a `QueryVTable` for each query.
520566
pub struct QueryVTables<'tcx> {
521567
$(
Lines changed: 3 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,18 @@
11
use std::fmt::Debug;
2-
use std::marker::PhantomData;
3-
use std::mem::transmute;
4-
use std::sync::Arc;
52

6-
use rustc_data_structures::sync::{DynSend, DynSync};
7-
use rustc_hir::def::DefKind;
8-
use rustc_span::Span;
93
use rustc_span::def_id::DefId;
104

115
use crate::dep_graph::DepKind;
6+
use crate::queries::QueryKeyId;
127

138
/// Description of a frame in the query stack.
149
///
1510
/// This is mostly used in case of cycles for error reporting.
1611
#[derive(Clone, Debug)]
17-
pub struct QueryStackFrame<I> {
18-
/// This field initially stores a `QueryStackDeferred` during collection,
19-
/// but can later be changed to `QueryStackFrameExtra` containing concrete information
20-
/// by calling `lift`. This is done so that collecting query does not need to invoke
21-
/// queries, instead `lift` will call queries in a more appropriate location.
22-
pub info: I,
23-
12+
pub struct QueryStackFrame<'tcx> {
13+
pub id: QueryKeyId<'tcx>,
2414
pub dep_kind: DepKind,
2515
pub def_id: Option<DefId>,
2616
/// A def-id that is extracted from a `Ty` in a query key
2717
pub def_id_for_ty_in_cycle: Option<DefId>,
2818
}
29-
30-
impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
31-
#[inline]
32-
pub fn new(
33-
info: QueryStackDeferred<'tcx>,
34-
dep_kind: DepKind,
35-
def_id: Option<DefId>,
36-
def_id_for_ty_in_cycle: Option<DefId>,
37-
) -> Self {
38-
Self { info, def_id, dep_kind, def_id_for_ty_in_cycle }
39-
}
40-
41-
pub fn lift(&self) -> QueryStackFrame<QueryStackFrameExtra> {
42-
QueryStackFrame {
43-
info: self.info.extract(),
44-
dep_kind: self.dep_kind,
45-
def_id: self.def_id,
46-
def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
47-
}
48-
}
49-
}
50-
51-
#[derive(Clone, Debug)]
52-
pub struct QueryStackFrameExtra {
53-
pub description: String,
54-
pub span: Option<Span>,
55-
pub def_kind: Option<DefKind>,
56-
}
57-
58-
impl QueryStackFrameExtra {
59-
#[inline]
60-
pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
61-
Self { description, span, def_kind }
62-
}
63-
64-
// FIXME(eddyb) Get more valid `Span`s on queries.
65-
#[inline]
66-
pub fn default_span(&self, span: Span) -> Span {
67-
if !span.is_dummy() {
68-
return span;
69-
}
70-
self.span.unwrap_or(span)
71-
}
72-
}
73-
74-
/// Track a 'side effect' for a particular query.
75-
/// This is used to hold a closure which can create `QueryStackFrameExtra`.
76-
#[derive(Clone)]
77-
pub struct QueryStackDeferred<'tcx> {
78-
_dummy: PhantomData<&'tcx ()>,
79-
80-
// `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
81-
// access it in the destructor.
82-
extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
83-
}
84-
85-
impl<'tcx> QueryStackDeferred<'tcx> {
86-
pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
87-
context: C,
88-
extract: fn(C) -> QueryStackFrameExtra,
89-
) -> Self {
90-
let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
91-
Arc::new(move || extract(context));
92-
// SAFETY: The `extract` closure does not access 'tcx in its destructor as the only
93-
// captured variable is `context` which is Copy and cannot have a destructor.
94-
Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
95-
}
96-
97-
pub fn extract(&self) -> QueryStackFrameExtra {
98-
(self.extract)()
99-
}
100-
}
101-
102-
impl<'tcx> Debug for QueryStackDeferred<'tcx> {
103-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104-
f.write_str("QueryStackDeferred")
105-
}
106-
}

compiler/rustc_query_impl/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ rustc_index = { path = "../rustc_index" }
1414
rustc_macros = { path = "../rustc_macros" }
1515
rustc_middle = { path = "../rustc_middle" }
1616
rustc_serialize = { path = "../rustc_serialize" }
17-
rustc_session = { path = "../rustc_session" }
1817
rustc_span = { path = "../rustc_span" }
1918
rustc_thread_pool = { path = "../rustc_thread_pool" }
2019
tracing = "0.1"

compiler/rustc_query_impl/src/execution.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_data_structures::sync::{DynSend, DynSync};
77
use rustc_data_structures::{outline, sharded, sync};
88
use rustc_errors::{FatalError, StashKey};
99
use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex};
10+
use rustc_middle::queries::QueryKeyId;
1011
use rustc_middle::query::plumbing::QueryVTable;
1112
use rustc_middle::query::{
1213
ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, QueryCache, QueryJob, QueryJobId,
@@ -50,8 +51,8 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool {
5051
/// grep for.)
5152
pub(crate) fn gather_active_jobs<'tcx, C>(
5253
query: &'tcx QueryVTable<'tcx, C>,
53-
tcx: TyCtxt<'tcx>,
5454
require_complete: bool,
55+
make_id: fn(C::Key) -> QueryKeyId<'tcx>,
5556
job_map_out: &mut QueryJobMap<'tcx>, // Out-param; job info is gathered into this map
5657
) -> Option<()>
5758
where
@@ -97,7 +98,7 @@ where
9798
// Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call
9899
// queries leading to a deadlock.
99100
for (key, job) in active {
100-
let frame = crate::plumbing::create_deferred_query_stack_frame(tcx, query, key);
101+
let frame = crate::plumbing::create_query_stack_frame(query, key, make_id);
101102
job_map_out.insert(job.id, QueryJobInfo { frame, job });
102103
}
103104

@@ -123,9 +124,9 @@ where
123124
fn mk_cycle<'tcx, C: QueryCache>(
124125
query: &'tcx QueryVTable<'tcx, C>,
125126
tcx: TyCtxt<'tcx>,
126-
cycle_error: CycleError,
127+
cycle_error: CycleError<'tcx>,
127128
) -> C::Value {
128-
let error = report_cycle(tcx.sess, &cycle_error);
129+
let error = report_cycle(tcx, &cycle_error);
129130
match query.cycle_error_handling {
130131
CycleErrorHandling::Error => {
131132
let guar = error.emit();
@@ -137,7 +138,8 @@ fn mk_cycle<'tcx, C: QueryCache>(
137138
}
138139
CycleErrorHandling::Stash => {
139140
let guar = if let Some(root) = cycle_error.cycle.first()
140-
&& let Some(span) = root.frame.info.span
141+
&& let span = root.frame.id.default_span(tcx, DUMMY_SP)
142+
&& !span.is_dummy()
141143
{
142144
error.stash(span, StashKey::Cycle).unwrap()
143145
} else {
@@ -225,7 +227,7 @@ fn cycle_error<'tcx, C: QueryCache>(
225227
.expect("failed to collect active queries");
226228

227229
let error = find_cycle_in_stack(try_execute, job_map, &current_query_job(tcx), span);
228-
(mk_cycle(query, tcx, error.lift()), None)
230+
(mk_cycle(query, tcx, error), None)
229231
}
230232

231233
#[inline(always)]
@@ -270,7 +272,7 @@ fn wait_for_query<'tcx, C: QueryCache>(
270272

271273
(v, Some(index))
272274
}
273-
Err(cycle) => (mk_cycle(query, tcx, cycle.lift()), None),
275+
Err(cycle) => (mk_cycle(query, tcx, cycle), None),
274276
}
275277
}
276278

0 commit comments

Comments
 (0)