Skip to content

Commit d53a01c

Browse files
Rollup merge of #153326 - Zalathar:query-modifiers, r=nnethercote
Make `rustc_with_all_queries!` pass query modifiers as named values This PR is a bold overhaul of how the proc-macro in `rustc_macros::query` passes query modifiers to the callback macros in `rustc_middle` and `rustc_query_impl`. The existing approach passes modifiers as a list that looks like `[(arena_cache), (no_hash)]`. That style requires a family of helper macros (`if_arena_cache!`, `if_no_hash!`) to check for modifiers when consuming the query list. This PR changes the proc-macro to instead pass modifiers like this: ```text { anon: false, arena_cache: true, cache_on_disk: false, ... } ``` This style allows each of the callback macros to deconstruct the modifier list in a relatively straightforward way, by binding the true/false literals to variables like `$arena_cache:literal`. One of the big advantages of this style is that we can write things like `#[cfg($arena_cache)]` and `#[cfg(not($arena_cache))]` to select blocks of code, eliminating the need for the `if_arena_cache!` family of helper macros. In follow-up PRs, we can also try to take advantage of the new modifier style to pass richer information for some modifiers, such as `desc` or `cache_on_disk_if`. That could potentially make it more reasonable to get rid of the `_description_fns` and `_cache_on_disk_if_fns` modules, as proposed in #153065. r? nnethercote
2 parents f3f0469 + 083b5db commit d53a01c

File tree

5 files changed

+260
-372
lines changed

5 files changed

+260
-372
lines changed

compiler/rustc_macros/src/query.rs

Lines changed: 74 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -137,54 +137,23 @@ struct CacheOnDiskIf {
137137
block: Block,
138138
}
139139

140+
/// See `rustc_middle::query::modifiers` for documentation of each query modifier.
140141
struct QueryModifiers {
141-
/// The description of the query.
142-
desc: Desc,
143-
144-
/// Use this type for the in-memory cache.
142+
// tidy-alphabetical-start
143+
anon: Option<Ident>,
145144
arena_cache: Option<Ident>,
146-
147-
/// Cache the query to disk if the `Block` returns true.
148145
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
154146
cycle_delay_bug: Option<Ident>,
155-
156-
/// A cycle error results in a stashed cycle error that can be unstashed and canceled later
147+
cycle_fatal: Option<Ident>,
157148
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
169149
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.
150+
desc: Desc,
151+
eval_always: Option<Ident>,
175152
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>`.
153+
no_hash: Option<Ident>,
187154
return_result_from_ensure_ok: Option<Ident>,
155+
separate_provide_extern: Option<Ident>,
156+
// tidy-alphabetical-end
188157
}
189158

190159
fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
@@ -272,6 +241,68 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
272241
})
273242
}
274243

244+
fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macro2::TokenStream {
245+
let QueryModifiers {
246+
// tidy-alphabetical-start
247+
anon,
248+
arena_cache,
249+
cache_on_disk_if,
250+
cycle_delay_bug,
251+
cycle_fatal,
252+
cycle_stash,
253+
depth_limit,
254+
desc: _,
255+
eval_always,
256+
feedable,
257+
no_hash,
258+
return_result_from_ensure_ok,
259+
separate_provide_extern,
260+
// tidy-alphabetical-end
261+
} = modifiers;
262+
263+
let anon = anon.is_some();
264+
let arena_cache = arena_cache.is_some();
265+
let cache_on_disk = cache_on_disk_if.is_some();
266+
267+
let cycle_error_handling = if cycle_delay_bug.is_some() {
268+
quote! { DelayBug }
269+
} else if cycle_fatal.is_some() {
270+
quote! { Fatal }
271+
} else if cycle_stash.is_some() {
272+
quote! { Stash }
273+
} else {
274+
quote! { Error }
275+
};
276+
277+
let depth_limit = depth_limit.is_some();
278+
let eval_always = eval_always.is_some();
279+
let feedable = feedable.is_some();
280+
let no_hash = no_hash.is_some();
281+
let return_result_from_ensure_ok = return_result_from_ensure_ok.is_some();
282+
let separate_provide_extern = separate_provide_extern.is_some();
283+
284+
// Giving an input span to the modifier names in the modifier list seems
285+
// to give slightly more helpful errors when one of the callback macros
286+
// fails to parse the modifier list.
287+
let query_name_span = query.name.span();
288+
quote_spanned! {
289+
query_name_span =>
290+
// Search for (QMODLIST) to find all occurrences of this query modifier list.
291+
// tidy-alphabetical-start
292+
anon: #anon,
293+
arena_cache: #arena_cache,
294+
cache_on_disk: #cache_on_disk,
295+
cycle_error_handling: #cycle_error_handling,
296+
depth_limit: #depth_limit,
297+
eval_always: #eval_always,
298+
feedable: #feedable,
299+
no_hash: #no_hash,
300+
return_result_from_ensure_ok: #return_result_from_ensure_ok,
301+
separate_provide_extern: #separate_provide_extern,
302+
// tidy-alphabetical-end
303+
}
304+
}
305+
275306
fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attribute> {
276307
use ::syn::*;
277308
let mut iter = list.iter();
@@ -458,51 +489,13 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
458489
ReturnType::Type(..) => quote! { #return_ty },
459490
};
460491

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),* };
492+
let modifiers_stream = make_modifiers_stream(&query, modifiers);
500493

501494
// Add the query to the group
502495
query_stream.extend(quote! {
503496
#(#doc_comments)*
504-
[#modifiers_stream]
505-
fn #name(#key_ty) #return_ty,
497+
fn #name(#key_ty) #return_ty
498+
{ #modifiers_stream }
506499
});
507500

508501
if let Some(feedable) = &modifiers.feedable {

compiler/rustc_middle/src/dep_graph/dep_node.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,10 @@ macro_rules! define_dep_nodes {
268268
queries {
269269
$(
270270
$(#[$q_attr:meta])*
271-
[$($modifiers:tt)*]
272-
fn $q_name:ident($K:ty) -> $V:ty,
271+
fn $q_name:ident($K:ty) -> $V:ty
272+
// Search for (QMODLIST) to find all occurrences of this query modifier list.
273+
// Query modifiers are currently not used here, so skip the whole list.
274+
{ $($modifiers:tt)* }
273275
)*
274276
}
275277
non_queries {

0 commit comments

Comments
 (0)