1
1
use proc_macro:: TokenStream ;
2
2
use proc_macro2:: { Delimiter , TokenTree } ;
3
- use quote:: quote;
3
+ use quote:: { quote, quote_spanned } ;
4
4
use syn:: parse:: { Parse , ParseStream , Result } ;
5
5
use syn:: punctuated:: Punctuated ;
6
6
use syn:: spanned:: Spanned ;
@@ -42,19 +42,19 @@ enum QueryModifier {
42
42
LoadCached ( Ident , Ident , Block ) ,
43
43
44
44
/// A cycle error for this query aborting the compilation with a fatal error.
45
- FatalCycle ,
45
+ FatalCycle ( Ident ) ,
46
46
47
47
/// A cycle error results in a delay_bug call
48
- CycleDelayBug ,
48
+ CycleDelayBug ( Ident ) ,
49
49
50
50
/// Don't hash the result, instead just mark a query red if it runs
51
- NoHash ,
51
+ NoHash ( Ident ) ,
52
52
53
53
/// Generate a dep node based on the dependencies of the query
54
- Anon ,
54
+ Anon ( Ident ) ,
55
55
56
56
/// Always evaluate the query, ignoring its dependencies
57
- EvalAlways ,
57
+ EvalAlways ( Ident ) ,
58
58
}
59
59
60
60
impl Parse for QueryModifier {
@@ -111,15 +111,15 @@ impl Parse for QueryModifier {
111
111
let ty = args. parse ( ) ?;
112
112
Ok ( QueryModifier :: Storage ( ty) )
113
113
} else if modifier == "fatal_cycle" {
114
- Ok ( QueryModifier :: FatalCycle )
114
+ Ok ( QueryModifier :: FatalCycle ( modifier ) )
115
115
} else if modifier == "cycle_delay_bug" {
116
- Ok ( QueryModifier :: CycleDelayBug )
116
+ Ok ( QueryModifier :: CycleDelayBug ( modifier ) )
117
117
} else if modifier == "no_hash" {
118
- Ok ( QueryModifier :: NoHash )
118
+ Ok ( QueryModifier :: NoHash ( modifier ) )
119
119
} else if modifier == "anon" {
120
- Ok ( QueryModifier :: Anon )
120
+ Ok ( QueryModifier :: Anon ( modifier ) )
121
121
} else if modifier == "eval_always" {
122
- Ok ( QueryModifier :: EvalAlways )
122
+ Ok ( QueryModifier :: EvalAlways ( modifier ) )
123
123
} else {
124
124
Err ( Error :: new ( modifier. span ( ) , "unknown query modifier" ) )
125
125
}
@@ -203,19 +203,19 @@ struct QueryModifiers {
203
203
load_cached : Option < ( Ident , Ident , Block ) > ,
204
204
205
205
/// A cycle error for this query aborting the compilation with a fatal error.
206
- fatal_cycle : bool ,
206
+ fatal_cycle : Option < Ident > ,
207
207
208
208
/// A cycle error results in a delay_bug call
209
- cycle_delay_bug : bool ,
209
+ cycle_delay_bug : Option < Ident > ,
210
210
211
211
/// Don't hash the result, instead just mark a query red if it runs
212
- no_hash : bool ,
212
+ no_hash : Option < Ident > ,
213
213
214
214
/// Generate a dep node based on the dependencies of the query
215
- anon : bool ,
215
+ anon : Option < Ident > ,
216
216
217
217
// Always evaluate the query, ignoring its dependencies
218
- eval_always : bool ,
218
+ eval_always : Option < Ident > ,
219
219
}
220
220
221
221
/// Process query modifiers into a struct, erroring on duplicates
@@ -224,11 +224,11 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
224
224
let mut storage = None ;
225
225
let mut cache = None ;
226
226
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 ;
232
232
for modifier in query. modifiers . 0 . drain ( ..) {
233
233
match modifier {
234
234
QueryModifier :: LoadCached ( tcx, id, block) => {
@@ -289,35 +289,35 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
289
289
}
290
290
desc = Some ( ( tcx, list) ) ;
291
291
}
292
- QueryModifier :: FatalCycle => {
293
- if fatal_cycle {
292
+ QueryModifier :: FatalCycle ( ident ) => {
293
+ if fatal_cycle. is_some ( ) {
294
294
panic ! ( "duplicate modifier `fatal_cycle` for query `{}`" , query. name) ;
295
295
}
296
- fatal_cycle = true ;
296
+ fatal_cycle = Some ( ident ) ;
297
297
}
298
- QueryModifier :: CycleDelayBug => {
299
- if cycle_delay_bug {
298
+ QueryModifier :: CycleDelayBug ( ident ) => {
299
+ if cycle_delay_bug. is_some ( ) {
300
300
panic ! ( "duplicate modifier `cycle_delay_bug` for query `{}`" , query. name) ;
301
301
}
302
- cycle_delay_bug = true ;
302
+ cycle_delay_bug = Some ( ident ) ;
303
303
}
304
- QueryModifier :: NoHash => {
305
- if no_hash {
304
+ QueryModifier :: NoHash ( ident ) => {
305
+ if no_hash. is_some ( ) {
306
306
panic ! ( "duplicate modifier `no_hash` for query `{}`" , query. name) ;
307
307
}
308
- no_hash = true ;
308
+ no_hash = Some ( ident ) ;
309
309
}
310
- QueryModifier :: Anon => {
311
- if anon {
310
+ QueryModifier :: Anon ( ident ) => {
311
+ if anon. is_some ( ) {
312
312
panic ! ( "duplicate modifier `anon` for query `{}`" , query. name) ;
313
313
}
314
- anon = true ;
314
+ anon = Some ( ident ) ;
315
315
}
316
- QueryModifier :: EvalAlways => {
317
- if eval_always {
316
+ QueryModifier :: EvalAlways ( ident ) => {
317
+ if eval_always. is_some ( ) {
318
318
panic ! ( "duplicate modifier `eval_always` for query `{}`" , query. name) ;
319
319
}
320
- eval_always = true ;
320
+ eval_always = Some ( ident ) ;
321
321
}
322
322
}
323
323
}
@@ -454,31 +454,39 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
454
454
let mut attributes = Vec :: new ( ) ;
455
455
456
456
// 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 } ) ;
459
459
} ;
460
460
// Pass on the storage modifier
461
461
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) } ) ;
463
464
} ;
464
465
// 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 } ) ;
467
468
} ;
468
469
// 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 } ) ;
471
472
} ;
472
473
// 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 } ) ;
475
476
} ;
476
477
// 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 } ) ;
479
480
} ;
480
481
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) , * } ;
482
490
let doc_comments = query. doc_comments . iter ( ) ;
483
491
// Add the query to the group
484
492
query_stream. extend ( quote ! {
0 commit comments