11use proc_macro:: TokenStream ;
22use proc_macro2:: { Delimiter , TokenTree } ;
3- use quote:: quote;
3+ use quote:: { quote, quote_spanned } ;
44use syn:: parse:: { Parse , ParseStream , Result } ;
55use syn:: punctuated:: Punctuated ;
66use 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
6060impl 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