11use proc_macro:: TokenStream ;
22use proc_macro2:: Span ;
3- use quote:: { quote, quote_spanned } ;
3+ use quote:: quote;
44use syn:: parse:: { Parse , ParseStream , Result } ;
55use syn:: punctuated:: Punctuated ;
66use syn:: spanned:: Spanned ;
77use syn:: {
8- AttrStyle , Attribute , Block , Error , Expr , Ident , Pat , ReturnType , Token , Type , braced,
9- parenthesized , parse_macro_input, token,
8+ AttrStyle , Attribute , Error , Expr , Ident , Pat , ReturnType , Token , Type , braced, parenthesized ,
9+ parse_macro_input, token,
1010} ;
1111
12+ mod modifiers;
13+
1214mod kw {
1315 syn:: custom_keyword!( non_query) ;
1416 syn:: custom_keyword!( query) ;
@@ -52,7 +54,7 @@ struct Query {
5254 key_ty : Type ,
5355 return_ty : ReturnType ,
5456
55- modifiers : QueryModifiers ,
57+ modifiers : modifiers :: QueryModifiers ,
5658}
5759
5860/// Declaration of a non-query dep kind.
@@ -102,7 +104,7 @@ impl Parse for QueryEntry {
102104 // Parse the query modifiers
103105 let braces_content;
104106 braced ! ( braces_content in input) ;
105- let modifiers = parse_query_modifiers ( & braces_content) ?;
107+ let modifiers = modifiers :: parse_query_modifiers ( & braces_content) ?;
106108
107109 // If there are no doc-comments, give at least some idea of what
108110 // it does by showing the query description.
@@ -127,151 +129,6 @@ impl<T: Parse> Parse for List<T> {
127129 }
128130}
129131
130- struct Desc {
131- modifier : Ident ,
132- expr_list : Punctuated < Expr , Token ! [ , ] > ,
133- }
134-
135- struct CacheOnDiskIf {
136- modifier : Ident ,
137- block : Block ,
138- }
139-
140- struct QueryModifiers {
141- /// The description of the query.
142- desc : Desc ,
143-
144- /// Use this type for the in-memory cache.
145- arena_cache : Option < Ident > ,
146-
147- /// Cache the query to disk if the `Block` returns true.
148- cache_on_disk_if : Option < CacheOnDiskIf > ,
149-
150- /// A cycle error for this query aborting the compilation with a fatal error.
151- cycle_fatal : Option < Ident > ,
152-
153- /// A cycle error results in a delay_bug call
154- cycle_delay_bug : Option < Ident > ,
155-
156- /// A cycle error results in a stashed cycle error that can be unstashed and canceled later
157- cycle_stash : Option < Ident > ,
158-
159- /// Don't hash the result, instead just mark a query red if it runs
160- no_hash : Option < Ident > ,
161-
162- /// Generate a dep node based on the dependencies of the query
163- anon : Option < Ident > ,
164-
165- /// Always evaluate the query, ignoring its dependencies
166- eval_always : Option < Ident > ,
167-
168- /// Whether the query has a call depth limit
169- depth_limit : Option < Ident > ,
170-
171- /// Use a separate query provider for local and extern crates
172- separate_provide_extern : Option < Ident > ,
173-
174- /// Generate a `feed` method to set the query's value from another query.
175- feedable : Option < Ident > ,
176-
177- /// When this query is called via `tcx.ensure_ok()`, it returns
178- /// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to
179- /// be executed, and that execution returns an error, the error result is
180- /// returned to the caller.
181- ///
182- /// If execution is skipped, a synthetic `Ok(())` is returned, on the
183- /// assumption that a query with all-green inputs must have succeeded.
184- ///
185- /// Can only be applied to queries with a return value of
186- /// `Result<_, ErrorGuaranteed>`.
187- return_result_from_ensure_ok : Option < Ident > ,
188- }
189-
190- fn parse_query_modifiers ( input : ParseStream < ' _ > ) -> Result < QueryModifiers > {
191- let mut arena_cache = None ;
192- let mut cache_on_disk_if = None ;
193- let mut desc = None ;
194- let mut cycle_fatal = None ;
195- let mut cycle_delay_bug = None ;
196- let mut cycle_stash = None ;
197- let mut no_hash = None ;
198- let mut anon = None ;
199- let mut eval_always = None ;
200- let mut depth_limit = None ;
201- let mut separate_provide_extern = None ;
202- let mut feedable = None ;
203- let mut return_result_from_ensure_ok = None ;
204-
205- while !input. is_empty ( ) {
206- let modifier: Ident = input. parse ( ) ?;
207-
208- macro_rules! try_insert {
209- ( $name: ident = $expr: expr) => {
210- if $name. is_some( ) {
211- return Err ( Error :: new( modifier. span( ) , "duplicate modifier" ) ) ;
212- }
213- $name = Some ( $expr) ;
214- } ;
215- }
216-
217- if modifier == "desc" {
218- // Parse a description modifier like:
219- // `desc { "foo {}", tcx.item_path(key) }`
220- let attr_content;
221- braced ! ( attr_content in input) ;
222- let expr_list = attr_content. parse_terminated ( Expr :: parse, Token ! [ , ] ) ?;
223- try_insert ! ( desc = Desc { modifier, expr_list } ) ;
224- } else if modifier == "cache_on_disk_if" {
225- // Parse a cache-on-disk modifier like:
226- // `cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) }`
227- let block = input. parse ( ) ?;
228- try_insert ! ( cache_on_disk_if = CacheOnDiskIf { modifier, block } ) ;
229- } else if modifier == "arena_cache" {
230- try_insert ! ( arena_cache = modifier) ;
231- } else if modifier == "cycle_fatal" {
232- try_insert ! ( cycle_fatal = modifier) ;
233- } else if modifier == "cycle_delay_bug" {
234- try_insert ! ( cycle_delay_bug = modifier) ;
235- } else if modifier == "cycle_stash" {
236- try_insert ! ( cycle_stash = modifier) ;
237- } else if modifier == "no_hash" {
238- try_insert ! ( no_hash = modifier) ;
239- } else if modifier == "anon" {
240- try_insert ! ( anon = modifier) ;
241- } else if modifier == "eval_always" {
242- try_insert ! ( eval_always = modifier) ;
243- } else if modifier == "depth_limit" {
244- try_insert ! ( depth_limit = modifier) ;
245- } else if modifier == "separate_provide_extern" {
246- try_insert ! ( separate_provide_extern = modifier) ;
247- } else if modifier == "feedable" {
248- try_insert ! ( feedable = modifier) ;
249- } else if modifier == "return_result_from_ensure_ok" {
250- try_insert ! ( return_result_from_ensure_ok = modifier) ;
251- } else {
252- return Err ( Error :: new ( modifier. span ( ) , "unknown query modifier" ) ) ;
253- }
254- }
255- let Some ( desc) = desc else {
256- return Err ( input. error ( "no description provided" ) ) ;
257- } ;
258- Ok ( QueryModifiers {
259- arena_cache,
260- cache_on_disk_if,
261- desc,
262- cycle_fatal,
263- cycle_delay_bug,
264- cycle_stash,
265- no_hash,
266- anon,
267- eval_always,
268- depth_limit,
269- separate_provide_extern,
270- feedable,
271- return_result_from_ensure_ok,
272- } )
273- }
274-
275132fn doc_comment_from_desc ( list : & Punctuated < Expr , token:: Comma > ) -> Result < Attribute > {
276133 use :: syn:: * ;
277134 let mut iter = list. iter ( ) ;
@@ -318,7 +175,7 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
318175 erased_name. set_span ( Span :: call_site ( ) ) ;
319176
320177 // Generate a function to check whether we should cache the query to disk, for some key.
321- if let Some ( CacheOnDiskIf { block, .. } ) = modifiers. cache_on_disk_if . as_ref ( ) {
178+ if let Some ( modifiers :: CacheOnDiskIf { block, .. } ) = modifiers. cache_on_disk_if . as_ref ( ) {
322179 // `disallowed_pass_by_ref` is needed because some keys are `rustc_pass_by_value`.
323180 streams. cache_on_disk_if_fns_stream . extend ( quote ! {
324181 #[ cfg_attr( not( bootstrap) , allow( unused_variables, rustc:: disallowed_pass_by_ref) ) ]
@@ -329,7 +186,7 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
329186 } ) ;
330187 }
331188
332- let Desc { expr_list, .. } = & modifiers. desc ;
189+ let modifiers :: Desc { expr_list, .. } = & modifiers. desc ;
333190
334191 let desc = quote ! {
335192 #[ allow( unused_variables) ]
@@ -356,7 +213,7 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
356213 crate :: query:: modifiers:: #name;
357214 } ) ;
358215
359- if let Some ( CacheOnDiskIf { modifier, .. } ) = & modifiers. cache_on_disk_if {
216+ if let Some ( modifiers :: CacheOnDiskIf { modifier, .. } ) = & modifiers. cache_on_disk_if {
360217 modifiers_stream. extend ( quote ! {
361218 crate :: query:: modifiers:: #modifier;
362219 } ) ;
@@ -458,51 +315,13 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
458315 ReturnType :: Type ( ..) => quote ! { #return_ty } ,
459316 } ;
460317
461- let mut modifiers_out = vec ! [ ] ;
462-
463- macro_rules! passthrough {
464- ( $( $modifier: ident ) ,+ $( , ) ? ) => {
465- $( if let Some ( $modifier) = & modifiers. $modifier {
466- modifiers_out. push( quote! { ( #$modifier) } ) ;
467- } ; ) +
468- }
469- }
470-
471- passthrough ! (
472- arena_cache,
473- cycle_fatal,
474- cycle_delay_bug,
475- cycle_stash,
476- no_hash,
477- anon,
478- eval_always,
479- feedable,
480- depth_limit,
481- separate_provide_extern,
482- return_result_from_ensure_ok,
483- ) ;
484-
485- // If there was a `cache_on_disk_if` modifier in the real input, pass
486- // on a synthetic `(cache_on_disk)` modifier that can be inspected by
487- // macro-rules macros.
488- if modifiers. cache_on_disk_if . is_some ( ) {
489- modifiers_out. push ( quote ! { ( cache_on_disk) } ) ;
490- }
491-
492- // This uses the span of the query definition for the commas,
493- // which can be important if we later encounter any ambiguity
494- // errors with any of the numerous macro_rules! macros that
495- // we use. Using the call-site span would result in a span pointing
496- // at the entire `rustc_queries!` invocation, which wouldn't
497- // be very useful.
498- let span = name. span ( ) ;
499- let modifiers_stream = quote_spanned ! { span => #( #modifiers_out) , * } ;
318+ let modifiers_stream = modifiers:: make_modifiers_stream ( & query, modifiers) ;
500319
501320 // Add the query to the group
502321 query_stream. extend ( quote ! {
503322 #( #doc_comments) *
504- [ #modifiers_stream ]
505- fn #name ( #key_ty ) #return_ty ,
323+ fn #name ( #key_ty ) #return_ty
324+ { #modifiers_stream }
506325 } ) ;
507326
508327 if let Some ( feedable) = & modifiers. feedable {
0 commit comments