@@ -30,14 +30,28 @@ fn check_attributes(attrs: Vec<Attribute>) -> Result<Vec<Attribute>> {
3030 attrs. into_iter ( ) . map ( inner) . collect ( )
3131}
3232
33- /// A compiler query. `query ... { ... }`
33+ /// Declaration of a compiler query.
34+ ///
35+ /// ```ignore (illustrative)
36+ /// /// Doc comment for `my_query`.
37+ /// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doc_comments
38+ /// query my_query(key: DefId) -> Value { anon }
39+ /// // ^^^^^^^^ name
40+ /// // ^^^ key_pat
41+ /// // ^^^^^ key_ty
42+ /// // ^^^^^^^^ return_ty
43+ /// // ^^^^ modifiers
44+ /// ```
3445struct Query {
3546 doc_comments : Vec < Attribute > ,
36- modifiers : QueryModifiers ,
3747 name : Ident ,
38- key : Pat ,
39- arg : Type ,
40- result : ReturnType ,
48+
49+ /// Parameter name for the key, or an arbitrary irrefutable pattern (e.g. `_`).
50+ key_pat : Pat ,
51+ key_ty : Type ,
52+ return_ty : ReturnType ,
53+
54+ modifiers : QueryModifiers ,
4155}
4256
4357impl Parse for Query {
@@ -47,26 +61,30 @@ impl Parse for Query {
4761 // Parse the query declaration. Like `query type_of(key: DefId) -> Ty<'tcx>`
4862 input. parse :: < kw:: query > ( ) ?;
4963 let name: Ident = input. parse ( ) ?;
50- let arg_content;
51- parenthesized ! ( arg_content in input) ;
52- let key = Pat :: parse_single ( & arg_content) ?;
53- arg_content. parse :: < Token ! [ : ] > ( ) ?;
54- let arg = arg_content. parse ( ) ?;
55- let _ = arg_content. parse :: < Option < Token ! [ , ] > > ( ) ?;
56- let result = input. parse ( ) ?;
64+
65+ // `(key: DefId)`
66+ let parens_content;
67+ parenthesized ! ( parens_content in input) ;
68+ let key_pat = Pat :: parse_single ( & parens_content) ?;
69+ parens_content. parse :: < Token ! [ : ] > ( ) ?;
70+ let key_ty = parens_content. parse :: < Type > ( ) ?;
71+ let _trailing_comma = parens_content. parse :: < Option < Token ! [ , ] > > ( ) ?;
72+
73+ // `-> Value`
74+ let return_ty = input. parse :: < ReturnType > ( ) ?;
5775
5876 // Parse the query modifiers
59- let content ;
60- braced ! ( content in input) ;
61- let modifiers = parse_query_modifiers ( & content ) ?;
77+ let braces_content ;
78+ braced ! ( braces_content in input) ;
79+ let modifiers = parse_query_modifiers ( & braces_content ) ?;
6280
6381 // If there are no doc-comments, give at least some idea of what
6482 // it does by showing the query description.
6583 if doc_comments. is_empty ( ) {
6684 doc_comments. push ( doc_comment_from_desc ( & modifiers. desc . expr_list ) ?) ;
6785 }
6886
69- Ok ( Query { doc_comments, modifiers, name, key , arg , result } )
87+ Ok ( Query { doc_comments, modifiers, name, key_pat , key_ty , return_ty } )
7088 }
7189}
7290
@@ -288,7 +306,7 @@ struct HelperTokenStreams {
288306}
289307
290308fn make_helpers_for_query ( query : & Query , streams : & mut HelperTokenStreams ) {
291- let Query { name, key , modifiers , arg , .. } = & query;
309+ let Query { name, key_pat , key_ty , modifiers , .. } = & query;
292310
293311 // Replace span for `name` to make rust-analyzer ignore it.
294312 let mut erased_name = name. clone ( ) ;
@@ -301,7 +319,7 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
301319 streams. cache_on_disk_if_fns_stream . extend ( quote ! {
302320 #[ allow( unused_variables, rustc:: pass_by_value) ]
303321 #[ inline]
304- pub fn #erased_name<' tcx>( #tcx: TyCtxt <' tcx>, #key : & crate :: queries:: #name:: Key <' tcx>) -> bool
322+ pub fn #erased_name<' tcx>( #tcx: TyCtxt <' tcx>, #key_pat : & crate :: queries:: #name:: Key <' tcx>) -> bool
305323 #block
306324 } ) ;
307325 }
@@ -311,8 +329,8 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
311329
312330 let desc = quote ! {
313331 #[ allow( unused_variables) ]
314- pub fn #erased_name<' tcx>( tcx: TyCtxt <' tcx>, key: #arg ) -> String {
315- let ( #tcx, #key ) = ( tcx, key) ;
332+ pub fn #erased_name<' tcx>( tcx: TyCtxt <' tcx>, key: #key_ty ) -> String {
333+ let ( #tcx, #key_pat ) = ( tcx, key) ;
316334 format!( #expr_list)
317335 }
318336 } ;
@@ -373,7 +391,7 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
373391 let mut erased_name = name. clone ( ) ;
374392 erased_name. set_span ( Span :: call_site ( ) ) ;
375393
376- let result = & query. result ;
394+ let result = & query. return_ty ;
377395
378396 // This dead code exists to instruct rust-analyzer about the link between the `rustc_queries`
379397 // query names and the corresponding produced provider. The issue is that by nature of this
@@ -417,19 +435,20 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
417435 }
418436
419437 for query in queries. 0 {
420- let Query { name, arg, modifiers, .. } = & query;
421- let result_full = & query. result ;
422- let result = match query. result {
438+ let Query { doc_comments, name, key_ty, return_ty, modifiers, .. } = & query;
439+
440+ // Normalize an absent return type into `-> ()` to make macro-rules parsing easier.
441+ let return_ty = match return_ty {
423442 ReturnType :: Default => quote ! { -> ( ) } ,
424- _ => quote ! { #result_full } ,
443+ ReturnType :: Type ( .. ) => quote ! { #return_ty } ,
425444 } ;
426445
427- let mut attributes = Vec :: new ( ) ;
446+ let mut modifiers_out = vec ! [ ] ;
428447
429448 macro_rules! passthrough {
430449 ( $( $modifier: ident ) ,+ $( , ) ? ) => {
431450 $( if let Some ( $modifier) = & modifiers. $modifier {
432- attributes . push( quote! { ( #$modifier) } ) ;
451+ modifiers_out . push( quote! { ( #$modifier) } ) ;
433452 } ; ) +
434453 }
435454 }
@@ -452,7 +471,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
452471 // on a synthetic `(cache_on_disk)` modifier that can be inspected by
453472 // macro-rules macros.
454473 if modifiers. cache_on_disk_if . is_some ( ) {
455- attributes . push ( quote ! { ( cache_on_disk) } ) ;
474+ modifiers_out . push ( quote ! { ( cache_on_disk) } ) ;
456475 }
457476
458477 // This uses the span of the query definition for the commas,
@@ -462,12 +481,13 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
462481 // at the entire `rustc_queries!` invocation, which wouldn't
463482 // be very useful.
464483 let span = name. span ( ) ;
465- let attribute_stream = quote_spanned ! { span=> #( #attributes ) , * } ;
466- let doc_comments = & query . doc_comments ;
484+ let modifiers_stream = quote_spanned ! { span => #( #modifiers_out ) , * } ;
485+
467486 // Add the query to the group
468487 query_stream. extend ( quote ! {
469488 #( #doc_comments) *
470- [ #attribute_stream] fn #name( #arg) #result,
489+ [ #modifiers_stream]
490+ fn #name( #key_ty) #return_ty,
471491 } ) ;
472492
473493 if let Some ( feedable) = & modifiers. feedable {
@@ -482,7 +502,8 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
482502 "Query {name} cannot be both `feedable` and `eval_always`."
483503 ) ;
484504 feedable_queries. extend ( quote ! {
485- [ #attribute_stream] fn #name( #arg) #result,
505+ [ #modifiers_stream]
506+ fn #name( #key_ty) #return_ty,
486507 } ) ;
487508 }
488509
0 commit comments