Skip to content

Commit 34fd06e

Browse files
Rollup merge of rust-lang#153161 - nnethercote:rejig-rustc_with_all_queries, r=Zalathar
Rejig `rustc_with_all_queries!` There are three things relating to `rustc_with_all_queries!` that have been bugging me. - `rustc_with_all_queries!`'s ability to receive `extra_fake_queries` lines like `[] fn Null(()) -> (),` where the only real thing is the `Null`, and everything is just pretending to be a normal query, ugh. - `make_dep_kind_array!`: a macro produced by one macro (`define_dep_nodes!`) and used by another macro (`define_queries!`) in another crate, ugh. - The `_dep_kind_vtable_ctors` module, which is a special module with no actual code that serves just a way of collecting vtable constructors from two different places so they can be referred to by `make_dep_kind_array!`, ugh. By making some adjustments to how `rustc_with_all_queries!` works, all three of these things are eliminated. r? @Zalathar
2 parents ef4cff2 + 40b2274 commit 34fd06e

6 files changed

Lines changed: 160 additions & 97 deletions

File tree

compiler/rustc_macros/src/query.rs

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use syn::{
1010
};
1111

1212
mod kw {
13+
syn::custom_keyword!(non_query);
1314
syn::custom_keyword!(query);
1415
}
1516

@@ -54,12 +55,37 @@ struct Query {
5455
modifiers: QueryModifiers,
5556
}
5657

57-
impl Parse for Query {
58+
/// Declaration of a non-query dep kind.
59+
/// ```ignore (illustrative)
60+
/// /// Doc comment for `MyNonQuery`.
61+
/// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doc_comments
62+
/// non_query MyNonQuery
63+
/// // ^^^^^^^^^^ name
64+
/// ```
65+
struct NonQuery {
66+
doc_comments: Vec<Attribute>,
67+
name: Ident,
68+
}
69+
70+
enum QueryEntry {
71+
Query(Query),
72+
NonQuery(NonQuery),
73+
}
74+
75+
impl Parse for QueryEntry {
5876
fn parse(input: ParseStream<'_>) -> Result<Self> {
5977
let mut doc_comments = check_attributes(input.call(Attribute::parse_outer)?)?;
6078

79+
// Try the non-query case first.
80+
if input.parse::<kw::non_query>().is_ok() {
81+
let name: Ident = input.parse()?;
82+
return Ok(QueryEntry::NonQuery(NonQuery { doc_comments, name }));
83+
}
84+
6185
// Parse the query declaration. Like `query type_of(key: DefId) -> Ty<'tcx>`
62-
input.parse::<kw::query>()?;
86+
if input.parse::<kw::query>().is_err() {
87+
return Err(input.error("expected `query` or `non_query`"));
88+
}
6389
let name: Ident = input.parse()?;
6490

6591
// `(key: DefId)`
@@ -84,7 +110,7 @@ impl Parse for Query {
84110
doc_comments.push(doc_comment_from_desc(&modifiers.desc.expr_list)?);
85111
}
86112

87-
Ok(Query { doc_comments, modifiers, name, key_pat, key_ty, return_ty })
113+
Ok(QueryEntry::Query(Query { doc_comments, modifiers, name, key_pat, key_ty, return_ty }))
88114
}
89115
}
90116

@@ -375,9 +401,9 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
375401
// macro producing a higher order macro that has all its token in the macro declaration we lose
376402
// any meaningful spans, resulting in rust-analyzer being unable to make the connection between
377403
// the query name and the corresponding providers field. The trick to fix this is to have
378-
// `rustc_queries` emit a field access with the given name's span which allows it to successfully
379-
// show references / go to definition to the corresponding provider assignment which is usually
380-
// the more interesting place.
404+
// `rustc_queries` emit a field access with the given name's span which allows it to
405+
// successfully show references / go to definition to the corresponding provider assignment
406+
// which is usually the more interesting place.
381407
let ra_hint = quote! {
382408
let crate::query::Providers { #name: _, .. };
383409
};
@@ -393,9 +419,10 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
393419
}
394420

395421
pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
396-
let queries = parse_macro_input!(input as List<Query>);
422+
let queries = parse_macro_input!(input as List<QueryEntry>);
397423

398424
let mut query_stream = quote! {};
425+
let mut non_query_stream = quote! {};
399426
let mut helpers = HelperTokenStreams::default();
400427
let mut analyzer_stream = quote! {};
401428
let mut errors = quote! {};
@@ -411,6 +438,18 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
411438
}
412439

413440
for query in queries.0 {
441+
let query = match query {
442+
QueryEntry::Query(query) => query,
443+
QueryEntry::NonQuery(NonQuery { doc_comments, name }) => {
444+
// Get the exceptional non-query case out of the way first.
445+
non_query_stream.extend(quote! {
446+
#(#doc_comments)*
447+
#name,
448+
});
449+
continue;
450+
}
451+
};
452+
414453
let Query { doc_comments, name, key_ty, return_ty, modifiers, .. } = &query;
415454

416455
// Normalize an absent return type into `-> ()` to make macro-rules parsing easier.
@@ -486,24 +525,18 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
486525
let HelperTokenStreams { description_fns_stream, cache_on_disk_if_fns_stream } = helpers;
487526

488527
TokenStream::from(quote! {
489-
/// Higher-order macro that invokes the specified macro with a prepared
490-
/// list of all query signatures (including modifiers).
491-
///
492-
/// This allows multiple simpler macros to each have access to the list
493-
/// of queries.
528+
/// Higher-order macro that invokes the specified macro with (a) a list of all query
529+
/// signatures (including modifiers), and (b) a list of non-query names. This allows
530+
/// multiple simpler macros to each have access to these lists.
494531
#[macro_export]
495532
macro_rules! rustc_with_all_queries {
496533
(
497-
// The macro to invoke once, on all queries (plus extras).
534+
// The macro to invoke once, on all queries and non-queries.
498535
$macro:ident!
499-
500-
// Within [], an optional list of extra "query" signatures to
501-
// pass to the given macro, in addition to the actual queries.
502-
$( [$($extra_fake_queries:tt)*] )?
503536
) => {
504537
$macro! {
505-
$( $($extra_fake_queries)* )?
506-
#query_stream
538+
queries { #query_stream }
539+
non_queries { #non_query_stream }
507540
}
508541
}
509542
}

compiler/rustc_middle/src/dep_graph/dep_node.rs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -265,18 +265,20 @@ impl StableOrd for WorkProductId {
265265
// Note: `$K` and `$V` are unused but present so this can be called by `rustc_with_all_queries`.
266266
macro_rules! define_dep_nodes {
267267
(
268-
$(
269-
$(#[$attr:meta])*
270-
[$($modifiers:tt)*] fn $variant:ident($K:ty) -> $V:ty,
271-
)*
272-
) => {
273-
274-
#[macro_export]
275-
macro_rules! make_dep_kind_array {
276-
($mod:ident) => {[ $($mod::$variant()),* ]};
268+
queries {
269+
$(
270+
$(#[$q_attr:meta])*
271+
[$($modifiers:tt)*]
272+
fn $q_name:ident($K:ty) -> $V:ty,
273+
)*
277274
}
278-
279-
/// This enum serves as an index into arrays built by `make_dep_kind_array`.
275+
non_queries {
276+
$(
277+
$(#[$nq_attr:meta])*
278+
$nq_name:ident,
279+
)*
280+
}
281+
) => {
280282
// This enum has more than u8::MAX variants so we need some kind of multi-byte
281283
// encoding. The derived Encodable/Decodable uses leb128 encoding which is
282284
// dense when only considering this enum. But DepKind is encoded in a larger
@@ -285,14 +287,18 @@ macro_rules! define_dep_nodes {
285287
#[allow(non_camel_case_types)]
286288
#[repr(u16)] // Must be kept in sync with the rest of `DepKind`.
287289
pub enum DepKind {
288-
$( $( #[$attr] )* $variant),*
290+
$( $(#[$nq_attr])* $nq_name, )*
291+
$( $(#[$q_attr])* $q_name, )*
289292
}
290293

291294
// This computes the number of dep kind variants. Along the way, it sanity-checks that the
292295
// discriminants of the variants have been assigned consecutively from 0 so that they can
293296
// be used as a dense index, and that all discriminants fit in a `u16`.
294297
pub(crate) const DEP_KIND_NUM_VARIANTS: u16 = {
295-
let deps = &[$(DepKind::$variant,)*];
298+
let deps = &[
299+
$(DepKind::$nq_name,)*
300+
$(DepKind::$q_name,)*
301+
];
296302
let mut i = 0;
297303
while i < deps.len() {
298304
if i != deps[i].as_usize() {
@@ -306,7 +312,8 @@ macro_rules! define_dep_nodes {
306312

307313
pub(super) fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
308314
match label {
309-
$( stringify!($variant) => Ok(self::DepKind::$variant), )*
315+
$( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )*
316+
$( stringify!($q_name) => Ok(self::DepKind::$q_name), )*
310317
_ => Err(()),
311318
}
312319
}
@@ -315,27 +322,14 @@ macro_rules! define_dep_nodes {
315322
/// DepNode groups for tests.
316323
#[expect(non_upper_case_globals)]
317324
pub mod label_strs {
318-
$( pub const $variant: &str = stringify!($variant); )*
325+
$( pub const $nq_name: &str = stringify!($nq_name); )*
326+
$( pub const $q_name: &str = stringify!($q_name); )*
319327
}
320328
};
321329
}
322330

323-
// Create various data structures for each query, and also for a few things
324-
// that aren't queries. The key and return types aren't used, hence the use of `()`.
325-
rustc_with_all_queries!(define_dep_nodes![
326-
/// We use this for most things when incr. comp. is turned off.
327-
[] fn Null(()) -> (),
328-
/// We use this to create a forever-red node.
329-
[] fn Red(()) -> (),
330-
/// We use this to create a side effect node.
331-
[] fn SideEffect(()) -> (),
332-
/// We use this to create the anon node with zero dependencies.
333-
[] fn AnonZeroDeps(()) -> (),
334-
[] fn TraitSelect(()) -> (),
335-
[] fn CompileCodegenUnit(()) -> (),
336-
[] fn CompileMonoItem(()) -> (),
337-
[] fn Metadata(()) -> (),
338-
]);
331+
// Create various data structures for each query, and also for a few things that aren't queries.
332+
rustc_with_all_queries! { define_dep_nodes! }
339333

340334
// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
341335
// Be very careful changing this type signature!

compiler/rustc_middle/src/queries.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,6 +2771,23 @@ rustc_queries! {
27712771
cache_on_disk_if { *cnum == LOCAL_CRATE }
27722772
separate_provide_extern
27732773
}
2774+
2775+
//-----------------------------------------------------------------------------
2776+
// "Non-queries" are special dep kinds that are not queries.
2777+
//-----------------------------------------------------------------------------
2778+
2779+
/// We use this for most things when incr. comp. is turned off.
2780+
non_query Null
2781+
/// We use this to create a forever-red node.
2782+
non_query Red
2783+
/// We use this to create a side effect node.
2784+
non_query SideEffect
2785+
/// We use this to create the anon node with zero dependencies.
2786+
non_query AnonZeroDeps
2787+
non_query TraitSelect
2788+
non_query CompileCodegenUnit
2789+
non_query CompileMonoItem
2790+
non_query Metadata
27742791
}
27752792

27762793
rustc_with_all_queries! { define_callbacks! }

compiler/rustc_middle/src/query/plumbing.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -375,11 +375,15 @@ macro_rules! define_callbacks {
375375
(
376376
// You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
377377
// `query_helper_param_ty!` can match on specific type names.
378-
$(
379-
$(#[$attr:meta])*
380-
[$($modifiers:tt)*]
381-
fn $name:ident($($K:tt)*) -> $V:ty,
382-
)*
378+
queries {
379+
$(
380+
$(#[$attr:meta])*
381+
[$($modifiers:tt)*]
382+
fn $name:ident($($K:tt)*) -> $V:ty,
383+
)*
384+
}
385+
// Non-queries are unused here.
386+
non_queries { $($_:tt)* }
383387
) => {
384388
$(
385389
#[allow(unused_lifetimes)]

compiler/rustc_query_impl/src/dep_kind_vtables.rs

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_middle::arena::Arena;
12
use rustc_middle::bug;
23
use rustc_middle::dep_graph::{DepKindVTable, DepNodeKey, KeyFingerprintStyle};
34
use rustc_middle::query::QueryCache;
@@ -124,24 +125,51 @@ where
124125
}
125126
}
126127

127-
/// Helper module containing a [`DepKindVTable`] constructor for each dep kind,
128-
/// for use with [`rustc_middle::make_dep_kind_array`].
129-
///
130-
/// That macro will check that we gave it a constructor for every known dep kind.
131-
mod _dep_kind_vtable_ctors {
132-
// Re-export all of the vtable constructors for non-query and query dep kinds.
133-
134-
// Non-query vtable constructors are defined in normal code.
135-
pub(crate) use super::non_query::*;
136-
// Query vtable constructors are defined via a macro.
137-
pub(crate) use crate::_dep_kind_vtable_ctors_for_queries::*;
128+
macro_rules! define_dep_kind_vtables {
129+
(
130+
queries {
131+
$(
132+
$(#[$attr:meta])*
133+
[$($modifiers:tt)*]
134+
fn $name:ident($K:ty) -> $V:ty,
135+
)*
136+
}
137+
non_queries {
138+
$(
139+
$(#[$nq_attr:meta])*
140+
$nq_name:ident,
141+
)*
142+
}
143+
) => {{
144+
// The small number of non-query vtables: `Null`, `Red`, etc.
145+
let nq_vtables = [
146+
$(
147+
non_query::$nq_name(),
148+
)*
149+
];
150+
151+
// The large number of query vtables.
152+
let q_vtables: [DepKindVTable<'tcx>; _] = [
153+
$(
154+
$crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
155+
$crate::query_impl::$name::VTableGetter,
156+
>(
157+
is_anon!([$($modifiers)*]),
158+
if_cache_on_disk!([$($modifiers)*] true false),
159+
is_eval_always!([$($modifiers)*]),
160+
)
161+
),*
162+
];
163+
164+
(nq_vtables, q_vtables)
165+
}}
138166
}
139167

140-
pub fn make_dep_kind_vtables<'tcx>(
141-
arena: &'tcx rustc_middle::arena::Arena<'tcx>,
142-
) -> &'tcx [DepKindVTable<'tcx>] {
143-
// Create an array of vtables, one for each dep kind (non-query and query).
144-
let dep_kind_vtables: [DepKindVTable<'tcx>; _] =
145-
rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors);
146-
arena.alloc_from_iter(dep_kind_vtables)
168+
// Create an array of vtables, one for each dep kind (non-query and query).
169+
pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] {
170+
let (nq_vtables, q_vtables) =
171+
rustc_middle::rustc_with_all_queries! { define_dep_kind_vtables! };
172+
173+
// Non-query vtables must come before query vtables, to match the order of `DepKind`.
174+
arena.alloc_from_iter(nq_vtables.into_iter().chain(q_vtables.into_iter()))
147175
}

compiler/rustc_query_impl/src/plumbing.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -414,15 +414,20 @@ pub(crate) fn force_from_dep_node_inner<'tcx, Q: GetQueryVTable<'tcx>>(
414414
}
415415
}
416416

417-
// Note: `$K` and `$V` are unused but present so this can be called by `rustc_with_all_queries`.
418417
macro_rules! define_queries {
419418
(
420-
$(
421-
$(#[$attr:meta])*
422-
[$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty,
423-
)*
419+
// Note: `$K` and `$V` are unused but present so this can be called by
420+
// `rustc_with_all_queries`.
421+
queries {
422+
$(
423+
$(#[$attr:meta])*
424+
[$($modifiers:tt)*]
425+
fn $name:ident($K:ty) -> $V:ty,
426+
)*
427+
}
428+
// Non-queries are unused here.
429+
non_queries { $($_:tt)* }
424430
) => {
425-
426431
pub(crate) mod query_impl { $(pub(crate) mod $name {
427432
use super::super::*;
428433
use ::rustc_middle::query::erase::{self, Erased};
@@ -689,23 +694,5 @@ macro_rules! define_queries {
689694
})
690695
}
691696
}
692-
693-
/// Declares a dep-kind vtable constructor for each query.
694-
mod _dep_kind_vtable_ctors_for_queries {
695-
use ::rustc_middle::dep_graph::DepKindVTable;
696-
use $crate::dep_kind_vtables::make_dep_kind_vtable_for_query;
697-
698-
$(
699-
/// `DepKindVTable` constructor for this query.
700-
pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> {
701-
use $crate::query_impl::$name::VTableGetter;
702-
make_dep_kind_vtable_for_query::<VTableGetter>(
703-
is_anon!([$($modifiers)*]),
704-
if_cache_on_disk!([$($modifiers)*] true false),
705-
is_eval_always!([$($modifiers)*]),
706-
)
707-
}
708-
)*
709-
}
710697
}
711698
}

0 commit comments

Comments
 (0)