Skip to content

Commit 301ad8a

Browse files
committed
Auto merge of #80891 - cjgillot:noq, r=Mark-Simulacrum
Make the `Query` enum a simple struct. A lot of code in `rustc_query_system` is generic over it, only to encode an exceptional error case: query cycles. The delayed computations are now done at cycle detection.
2 parents fe1bf8e + 903f65f commit 301ad8a

File tree

12 files changed

+297
-314
lines changed

12 files changed

+297
-314
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4202,6 +4202,7 @@ dependencies = [
42024202
"rustc_index",
42034203
"rustc_macros",
42044204
"rustc_serialize",
4205+
"rustc_session",
42054206
"rustc_span",
42064207
"smallvec 1.6.1",
42074208
"tracing",

compiler/rustc_middle/src/dep_graph/mod.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::ich::StableHashingContext;
22
use crate::ty::{self, TyCtxt};
33
use rustc_data_structures::profiling::SelfProfilerRef;
44
use rustc_data_structures::sync::Lock;
5+
use rustc_session::Session;
56

67
#[macro_use]
78
mod dep_node;
@@ -101,20 +102,18 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
101102
TyCtxt::create_stable_hashing_context(*self)
102103
}
103104

104-
fn debug_dep_tasks(&self) -> bool {
105-
self.sess.opts.debugging_opts.dep_tasks
106-
}
107-
fn debug_dep_node(&self) -> bool {
108-
self.sess.opts.debugging_opts.incremental_info
109-
|| self.sess.opts.debugging_opts.query_dep_graph
110-
}
111-
112105
#[inline]
113106
fn dep_graph(&self) -> &DepGraph {
114107
&self.dep_graph
115108
}
116109

110+
#[inline(always)]
117111
fn profiler(&self) -> &SelfProfilerRef {
118112
&self.prof
119113
}
114+
115+
#[inline(always)]
116+
fn sess(&self) -> &Session {
117+
self.sess
118+
}
120119
}

compiler/rustc_query_impl/src/lib.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,17 @@ extern crate rustc_middle;
1717
extern crate tracing;
1818

1919
use rustc_data_structures::fingerprint::Fingerprint;
20-
use rustc_data_structures::fx::FxHashMap;
2120
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
22-
use rustc_errors::{Diagnostic, Handler, Level};
21+
use rustc_errors::{DiagnosticBuilder, Handler};
2322
use rustc_hir::def_id::CrateNum;
2423
use rustc_index::vec::IndexVec;
2524
use rustc_middle::dep_graph;
2625
use rustc_middle::ich::StableHashingContext;
2726
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
2827
use rustc_middle::ty::query::{Providers, QueryEngine};
29-
use rustc_middle::ty::TyCtxt;
28+
use rustc_middle::ty::{self, TyCtxt};
3029
use rustc_serialize::opaque;
3130
use rustc_span::{Span, DUMMY_SP};
32-
use std::mem;
3331

3432
#[macro_use]
3533
mod plumbing;

compiler/rustc_query_impl/src/plumbing.rs

+52-164
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,19 @@
22
//! generate the actual methods on tcx which find and execute the provider,
33
//! manage the caches, and so forth.
44
5-
use super::{queries, Query};
5+
use super::queries;
66
use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeExt, DepNodeIndex, SerializedDepNodeIndex};
77
use rustc_middle::ty::query::on_disk_cache;
88
use rustc_middle::ty::tls::{self, ImplicitCtxt};
99
use rustc_middle::ty::{self, TyCtxt};
1010
use rustc_query_system::dep_graph::HasDepContext;
11-
use rustc_query_system::query::{CycleError, QueryJobId, QueryJobInfo};
12-
use rustc_query_system::query::{QueryContext, QueryDescription};
11+
use rustc_query_system::query::{QueryContext, QueryDescription, QueryJobId, QueryMap};
1312

14-
use rustc_data_structures::fx::FxHashMap;
1513
use rustc_data_structures::sync::Lock;
1614
use rustc_data_structures::thin_vec::ThinVec;
17-
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder};
15+
use rustc_errors::Diagnostic;
1816
use rustc_serialize::opaque;
1917
use rustc_span::def_id::{DefId, LocalDefId};
20-
use rustc_span::Span;
2118

2219
#[derive(Copy, Clone)]
2320
pub struct QueryCtxt<'tcx> {
@@ -45,15 +42,6 @@ impl HasDepContext for QueryCtxt<'tcx> {
4542
}
4643

4744
impl QueryContext for QueryCtxt<'tcx> {
48-
type Query = Query<'tcx>;
49-
50-
fn incremental_verify_ich(&self) -> bool {
51-
self.sess.opts.debugging_opts.incremental_verify_ich
52-
}
53-
fn verbose(&self) -> bool {
54-
self.sess.verbose()
55-
}
56-
5745
fn def_path_str(&self, def_id: DefId) -> String {
5846
self.tcx.def_path_str(def_id)
5947
}
@@ -62,11 +50,8 @@ impl QueryContext for QueryCtxt<'tcx> {
6250
tls::with_related_context(**self, |icx| icx.query)
6351
}
6452

65-
fn try_collect_active_jobs(
66-
&self,
67-
) -> Option<FxHashMap<QueryJobId<Self::DepKind>, QueryJobInfo<Self::DepKind, Self::Query>>>
68-
{
69-
self.queries.try_collect_active_jobs()
53+
fn try_collect_active_jobs(&self) -> Option<QueryMap<Self::DepKind>> {
54+
self.queries.try_collect_active_jobs(**self)
7055
}
7156

7257
fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) {
@@ -132,14 +117,6 @@ impl QueryContext for QueryCtxt<'tcx> {
132117
(cb.force_from_dep_node)(*self, dep_node)
133118
}
134119

135-
fn has_errors_or_delayed_span_bugs(&self) -> bool {
136-
self.sess.has_errors_or_delayed_span_bugs()
137-
}
138-
139-
fn diagnostic(&self) -> &rustc_errors::Handler {
140-
self.sess.diagnostic()
141-
}
142-
143120
// Interactions with on_disk_cache
144121
fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
145122
self.on_disk_cache
@@ -196,54 +173,6 @@ impl QueryContext for QueryCtxt<'tcx> {
196173
}
197174

198175
impl<'tcx> QueryCtxt<'tcx> {
199-
#[inline(never)]
200-
#[cold]
201-
pub(super) fn report_cycle(
202-
self,
203-
CycleError { usage, cycle: stack }: CycleError<Query<'tcx>>,
204-
) -> DiagnosticBuilder<'tcx> {
205-
assert!(!stack.is_empty());
206-
207-
let fix_span = |span: Span, query: &Query<'tcx>| {
208-
self.sess.source_map().guess_head_span(query.default_span(*self, span))
209-
};
210-
211-
// Disable naming impls with types in this path, since that
212-
// sometimes cycles itself, leading to extra cycle errors.
213-
// (And cycle errors around impls tend to occur during the
214-
// collect/coherence phases anyhow.)
215-
ty::print::with_forced_impl_filename_line(|| {
216-
let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
217-
let mut err = struct_span_err!(
218-
self.sess,
219-
span,
220-
E0391,
221-
"cycle detected when {}",
222-
stack[0].query.describe(self)
223-
);
224-
225-
for i in 1..stack.len() {
226-
let query = &stack[i].query;
227-
let span = fix_span(stack[(i + 1) % stack.len()].span, query);
228-
err.span_note(span, &format!("...which requires {}...", query.describe(self)));
229-
}
230-
231-
err.note(&format!(
232-
"...which again requires {}, completing the cycle",
233-
stack[0].query.describe(self)
234-
));
235-
236-
if let Some((span, query)) = usage {
237-
err.span_note(
238-
fix_span(span, &query),
239-
&format!("cycle used when {}", query.describe(self)),
240-
);
241-
}
242-
243-
err
244-
})
245-
}
246-
247176
pub(super) fn encode_query_results(
248177
self,
249178
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
@@ -323,16 +252,16 @@ pub struct QueryStruct {
323252

324253
macro_rules! handle_cycle_error {
325254
([][$tcx: expr, $error:expr]) => {{
326-
$tcx.report_cycle($error).emit();
255+
$error.emit();
327256
Value::from_cycle_error($tcx)
328257
}};
329258
([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{
330-
$tcx.report_cycle($error).emit();
259+
$error.emit();
331260
$tcx.sess.abort_if_errors();
332261
unreachable!()
333262
}};
334263
([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{
335-
$tcx.report_cycle($error).delay_as_bug();
264+
$error.delay_as_bug();
336265
Value::from_cycle_error($tcx)
337266
}};
338267
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
@@ -386,55 +315,40 @@ macro_rules! define_queries {
386315
input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
387316
}
388317

389-
#[allow(nonstandard_style)]
390-
#[derive(Clone, Debug)]
391-
pub enum Query<$tcx> {
392-
$($(#[$attr])* $name(query_keys::$name<$tcx>)),*
393-
}
394-
395-
impl<$tcx> Query<$tcx> {
396-
pub fn name(&self) -> &'static str {
397-
match *self {
398-
$(Query::$name(_) => stringify!($name),)*
399-
}
400-
}
318+
mod make_query {
319+
use super::*;
401320

402-
pub(crate) fn describe(&self, tcx: QueryCtxt<$tcx>) -> String {
403-
let (r, name) = match *self {
404-
$(Query::$name(key) => {
405-
(queries::$name::describe(tcx, key), stringify!($name))
406-
})*
321+
// Create an eponymous constructor for each query.
322+
$(#[allow(nonstandard_style)] $(#[$attr])*
323+
pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame {
324+
let kind = dep_graph::DepKind::$name;
325+
let name = stringify!($name);
326+
let description = ty::print::with_forced_impl_filename_line(
327+
// Force filename-line mode to avoid invoking `type_of` query.
328+
|| queries::$name::describe(tcx, key)
329+
);
330+
let description = if tcx.sess.verbose() {
331+
format!("{} [{}]", description, name)
332+
} else {
333+
description
407334
};
408-
if tcx.sess.verbose() {
409-
format!("{} [{}]", r, name)
335+
let span = if kind == dep_graph::DepKind::def_span {
336+
// The `def_span` query is used to calculate `default_span`,
337+
// so exit to avoid infinite recursion.
338+
None
410339
} else {
411-
r
412-
}
413-
}
414-
415-
// FIXME(eddyb) Get more valid `Span`s on queries.
416-
pub fn default_span(&self, tcx: TyCtxt<$tcx>, span: Span) -> Span {
417-
if !span.is_dummy() {
418-
return span;
419-
}
420-
// The `def_span` query is used to calculate `default_span`,
421-
// so exit to avoid infinite recursion.
422-
if let Query::def_span(..) = *self {
423-
return span
424-
}
425-
match *self {
426-
$(Query::$name(key) => key.default_span(tcx),)*
427-
}
428-
}
429-
}
340+
Some(key.default_span(*tcx))
341+
};
342+
let hash = || {
343+
let mut hcx = tcx.create_stable_hashing_context();
344+
let mut hasher = StableHasher::new();
345+
std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
346+
key.hash_stable(&mut hcx, &mut hasher);
347+
hasher.finish::<u64>()
348+
};
430349

431-
impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> {
432-
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
433-
mem::discriminant(self).hash_stable(hcx, hasher);
434-
match *self {
435-
$(Query::$name(key) => key.hash_stable(hcx, hasher),)*
436-
}
437-
}
350+
QueryStackFrame::new(name, description, span, hash)
351+
})*
438352
}
439353

440354
#[allow(nonstandard_style)]
@@ -461,7 +375,9 @@ macro_rules! define_queries {
461375
type Cache = query_storage::$name<$tcx>;
462376

463377
#[inline(always)]
464-
fn query_state<'a>(tcx: QueryCtxt<$tcx>) -> &'a QueryState<crate::dep_graph::DepKind, Query<$tcx>, Self::Key> {
378+
fn query_state<'a>(tcx: QueryCtxt<$tcx>) -> &'a QueryState<crate::dep_graph::DepKind, Self::Key>
379+
where QueryCtxt<$tcx>: 'a
380+
{
465381
&tcx.queries.$name
466382
}
467383

@@ -493,7 +409,7 @@ macro_rules! define_queries {
493409

494410
fn handle_cycle_error(
495411
tcx: QueryCtxt<'tcx>,
496-
error: CycleError<Query<'tcx>>
412+
mut error: DiagnosticBuilder<'_>,
497413
) -> Self::Value {
498414
handle_cycle_error!([$($modifiers)*][tcx, error])
499415
}
@@ -596,7 +512,6 @@ macro_rules! define_queries_struct {
596512

597513
$($(#[$attr])* $name: QueryState<
598514
crate::dep_graph::DepKind,
599-
Query<$tcx>,
600515
query_keys::$name<$tcx>,
601516
>,)*
602517
}
@@ -614,14 +529,17 @@ macro_rules! define_queries_struct {
614529
}
615530

616531
pub(crate) fn try_collect_active_jobs(
617-
&self
618-
) -> Option<FxHashMap<QueryJobId<crate::dep_graph::DepKind>, QueryJobInfo<crate::dep_graph::DepKind, Query<$tcx>>>> {
619-
let mut jobs = FxHashMap::default();
532+
&$tcx self,
533+
tcx: TyCtxt<$tcx>,
534+
) -> Option<QueryMap<crate::dep_graph::DepKind>> {
535+
let tcx = QueryCtxt { tcx, queries: self };
536+
let mut jobs = QueryMap::default();
620537

621538
$(
622539
self.$name.try_collect_active_jobs(
623-
<queries::$name<'tcx> as QueryAccessors<QueryCtxt<'tcx>>>::DEP_KIND,
624-
Query::$name,
540+
tcx,
541+
dep_graph::DepKind::$name,
542+
make_query::$name,
625543
&mut jobs,
626544
)?;
627545
)*
@@ -666,38 +584,8 @@ macro_rules! define_queries_struct {
666584
handler: &Handler,
667585
num_frames: Option<usize>,
668586
) -> usize {
669-
let query_map = self.try_collect_active_jobs();
670-
671-
let mut current_query = query;
672-
let mut i = 0;
673-
674-
while let Some(query) = current_query {
675-
if Some(i) == num_frames {
676-
break;
677-
}
678-
let query_info = if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query))
679-
{
680-
info
681-
} else {
682-
break;
683-
};
684-
let mut diag = Diagnostic::new(
685-
Level::FailureNote,
686-
&format!(
687-
"#{} [{}] {}",
688-
i,
689-
query_info.info.query.name(),
690-
query_info.info.query.describe(QueryCtxt { tcx, queries: self })
691-
),
692-
);
693-
diag.span = tcx.sess.source_map().guess_head_span(query_info.info.span).into();
694-
handler.force_print_diagnostic(diag);
695-
696-
current_query = query_info.job.parent;
697-
i += 1;
698-
}
699-
700-
i
587+
let qcx = QueryCtxt { tcx, queries: self };
588+
rustc_query_system::query::print_query_stack(qcx, query, handler, num_frames)
701589
}
702590

703591
$($(#[$attr])*

compiler/rustc_query_system/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ rustc_errors = { path = "../rustc_errors" }
1616
rustc_macros = { path = "../rustc_macros" }
1717
rustc_index = { path = "../rustc_index" }
1818
rustc_serialize = { path = "../rustc_serialize" }
19+
rustc_session = { path = "../rustc_session" }
1920
rustc_span = { path = "../rustc_span" }
2021
parking_lot = "0.11"
2122
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }

0 commit comments

Comments
 (0)