Skip to content

Commit 34f1161

Browse files
committedJun 8, 2021
Preserve more spans in internal rustc_queries! macro
We now preserve the span of the various query modifiers, and use the span of the query's name for the commas that we generate to separate the modifiers. This makes debugging issues with the internal query macro infrastructure much nicer - previously, we would get errors messages pointing at the entire call site (the `rustc_queries!` invocation), which isn't very useful. This should have no effect when compilation succeeds. A concrete example of an error message produced after this changed: ``` error: local ambiguity: multiple parsing options: built-in NTs tt ('modifiers') or 1 other option. --> /home/aaron/repos/rust/compiler/rustc_middle/src/query/mod.rs:23:11 | 12 | / rustc_queries! { 13 | | query trigger_delay_span_bug(key: DefId) -> () { 14 | | desc { "trigger a delay span bug" } 15 | | } ... | 23 | | query hir_crate(key: ()) -> &'tcx Crate<'tcx> { | | ^^^^^^^^^ ... | 1715 | | } 1716 | | } | |_- in this expansion of `rustc_query_append!` | ::: compiler/rustc_query_impl/src/lib.rs:51:1 | 51 | rustc_query_append! { [define_queries!][<'tcx>] } | ------------------------------------------------- in this macro invocation ``` The particular bug shown in this error message will be fixed in a separate PR.
1 parent e4a6032 commit 34f1161

File tree

1 file changed

+56
-48
lines changed

1 file changed

+56
-48
lines changed
 

‎compiler/rustc_macros/src/query.rs

+56-48
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use proc_macro::TokenStream;
22
use proc_macro2::{Delimiter, TokenTree};
3-
use quote::quote;
3+
use quote::{quote, quote_spanned};
44
use syn::parse::{Parse, ParseStream, Result};
55
use syn::punctuated::Punctuated;
66
use syn::spanned::Spanned;
@@ -42,19 +42,19 @@ enum QueryModifier {
4242
LoadCached(Ident, Ident, Block),
4343

4444
/// A cycle error for this query aborting the compilation with a fatal error.
45-
FatalCycle,
45+
FatalCycle(Ident),
4646

4747
/// A cycle error results in a delay_bug call
48-
CycleDelayBug,
48+
CycleDelayBug(Ident),
4949

5050
/// Don't hash the result, instead just mark a query red if it runs
51-
NoHash,
51+
NoHash(Ident),
5252

5353
/// Generate a dep node based on the dependencies of the query
54-
Anon,
54+
Anon(Ident),
5555

5656
/// Always evaluate the query, ignoring its dependencies
57-
EvalAlways,
57+
EvalAlways(Ident),
5858
}
5959

6060
impl Parse for QueryModifier {
@@ -111,15 +111,15 @@ impl Parse for QueryModifier {
111111
let ty = args.parse()?;
112112
Ok(QueryModifier::Storage(ty))
113113
} else if modifier == "fatal_cycle" {
114-
Ok(QueryModifier::FatalCycle)
114+
Ok(QueryModifier::FatalCycle(modifier))
115115
} else if modifier == "cycle_delay_bug" {
116-
Ok(QueryModifier::CycleDelayBug)
116+
Ok(QueryModifier::CycleDelayBug(modifier))
117117
} else if modifier == "no_hash" {
118-
Ok(QueryModifier::NoHash)
118+
Ok(QueryModifier::NoHash(modifier))
119119
} else if modifier == "anon" {
120-
Ok(QueryModifier::Anon)
120+
Ok(QueryModifier::Anon(modifier))
121121
} else if modifier == "eval_always" {
122-
Ok(QueryModifier::EvalAlways)
122+
Ok(QueryModifier::EvalAlways(modifier))
123123
} else {
124124
Err(Error::new(modifier.span(), "unknown query modifier"))
125125
}
@@ -203,19 +203,19 @@ struct QueryModifiers {
203203
load_cached: Option<(Ident, Ident, Block)>,
204204

205205
/// A cycle error for this query aborting the compilation with a fatal error.
206-
fatal_cycle: bool,
206+
fatal_cycle: Option<Ident>,
207207

208208
/// A cycle error results in a delay_bug call
209-
cycle_delay_bug: bool,
209+
cycle_delay_bug: Option<Ident>,
210210

211211
/// Don't hash the result, instead just mark a query red if it runs
212-
no_hash: bool,
212+
no_hash: Option<Ident>,
213213

214214
/// Generate a dep node based on the dependencies of the query
215-
anon: bool,
215+
anon: Option<Ident>,
216216

217217
// Always evaluate the query, ignoring its dependencies
218-
eval_always: bool,
218+
eval_always: Option<Ident>,
219219
}
220220

221221
/// Process query modifiers into a struct, erroring on duplicates
@@ -224,11 +224,11 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
224224
let mut storage = None;
225225
let mut cache = None;
226226
let mut desc = None;
227-
let mut fatal_cycle = false;
228-
let mut cycle_delay_bug = false;
229-
let mut no_hash = false;
230-
let mut anon = false;
231-
let mut eval_always = false;
227+
let mut fatal_cycle = None;
228+
let mut cycle_delay_bug = None;
229+
let mut no_hash = None;
230+
let mut anon = None;
231+
let mut eval_always = None;
232232
for modifier in query.modifiers.0.drain(..) {
233233
match modifier {
234234
QueryModifier::LoadCached(tcx, id, block) => {
@@ -289,35 +289,35 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
289289
}
290290
desc = Some((tcx, list));
291291
}
292-
QueryModifier::FatalCycle => {
293-
if fatal_cycle {
292+
QueryModifier::FatalCycle(ident) => {
293+
if fatal_cycle.is_some() {
294294
panic!("duplicate modifier `fatal_cycle` for query `{}`", query.name);
295295
}
296-
fatal_cycle = true;
296+
fatal_cycle = Some(ident);
297297
}
298-
QueryModifier::CycleDelayBug => {
299-
if cycle_delay_bug {
298+
QueryModifier::CycleDelayBug(ident) => {
299+
if cycle_delay_bug.is_some() {
300300
panic!("duplicate modifier `cycle_delay_bug` for query `{}`", query.name);
301301
}
302-
cycle_delay_bug = true;
302+
cycle_delay_bug = Some(ident);
303303
}
304-
QueryModifier::NoHash => {
305-
if no_hash {
304+
QueryModifier::NoHash(ident) => {
305+
if no_hash.is_some() {
306306
panic!("duplicate modifier `no_hash` for query `{}`", query.name);
307307
}
308-
no_hash = true;
308+
no_hash = Some(ident);
309309
}
310-
QueryModifier::Anon => {
311-
if anon {
310+
QueryModifier::Anon(ident) => {
311+
if anon.is_some() {
312312
panic!("duplicate modifier `anon` for query `{}`", query.name);
313313
}
314-
anon = true;
314+
anon = Some(ident);
315315
}
316-
QueryModifier::EvalAlways => {
317-
if eval_always {
316+
QueryModifier::EvalAlways(ident) => {
317+
if eval_always.is_some() {
318318
panic!("duplicate modifier `eval_always` for query `{}`", query.name);
319319
}
320-
eval_always = true;
320+
eval_always = Some(ident);
321321
}
322322
}
323323
}
@@ -454,31 +454,39 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
454454
let mut attributes = Vec::new();
455455

456456
// Pass on the fatal_cycle modifier
457-
if modifiers.fatal_cycle {
458-
attributes.push(quote! { fatal_cycle });
457+
if let Some(fatal_cycle) = &modifiers.fatal_cycle {
458+
attributes.push(quote! { #fatal_cycle });
459459
};
460460
// Pass on the storage modifier
461461
if let Some(ref ty) = modifiers.storage {
462-
attributes.push(quote! { storage(#ty) });
462+
let span = ty.span();
463+
attributes.push(quote_spanned! {span=> storage(#ty) });
463464
};
464465
// Pass on the cycle_delay_bug modifier
465-
if modifiers.cycle_delay_bug {
466-
attributes.push(quote! { cycle_delay_bug });
466+
if let Some(cycle_delay_bug) = &modifiers.cycle_delay_bug {
467+
attributes.push(quote! { #cycle_delay_bug });
467468
};
468469
// Pass on the no_hash modifier
469-
if modifiers.no_hash {
470-
attributes.push(quote! { no_hash });
470+
if let Some(no_hash) = &modifiers.no_hash {
471+
attributes.push(quote! { #no_hash });
471472
};
472473
// Pass on the anon modifier
473-
if modifiers.anon {
474-
attributes.push(quote! { anon });
474+
if let Some(anon) = &modifiers.anon {
475+
attributes.push(quote! { #anon });
475476
};
476477
// Pass on the eval_always modifier
477-
if modifiers.eval_always {
478-
attributes.push(quote! { eval_always });
478+
if let Some(eval_always) = &modifiers.eval_always {
479+
attributes.push(quote! { #eval_always });
479480
};
480481

481-
let attribute_stream = quote! {#(#attributes),*};
482+
// This uses the span of the query definition for the commas,
483+
// which can be important if we later encounter any ambiguity
484+
// errors with any of the numerous macro_rules! macros that
485+
// we use. Using the call-site span would result in a span pointing
486+
// at the entire `rustc_queries!` invocation, which wouldn't
487+
// be very useful.
488+
let span = name.span();
489+
let attribute_stream = quote_spanned! {span=> #(#attributes),*};
482490
let doc_comments = query.doc_comments.iter();
483491
// Add the query to the group
484492
query_stream.extend(quote! {

0 commit comments

Comments
 (0)
Please sign in to comment.