diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index cd9c53134ae2..721cc7fe4d9b 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -10,6 +10,7 @@ }; mod kw { + syn::custom_keyword!(non_query); syn::custom_keyword!(query); } @@ -54,12 +55,37 @@ struct Query { modifiers: QueryModifiers, } -impl Parse for Query { +/// Declaration of a non-query dep kind. +/// ```ignore (illustrative) +/// /// Doc comment for `MyNonQuery`. +/// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doc_comments +/// non_query MyNonQuery +/// // ^^^^^^^^^^ name +/// ``` +struct NonQuery { + doc_comments: Vec, + name: Ident, +} + +enum QueryEntry { + Query(Query), + NonQuery(NonQuery), +} + +impl Parse for QueryEntry { fn parse(input: ParseStream<'_>) -> Result { let mut doc_comments = check_attributes(input.call(Attribute::parse_outer)?)?; + // Try the non-query case first. + if input.parse::().is_ok() { + let name: Ident = input.parse()?; + return Ok(QueryEntry::NonQuery(NonQuery { doc_comments, name })); + } + // Parse the query declaration. Like `query type_of(key: DefId) -> Ty<'tcx>` - input.parse::()?; + if input.parse::().is_err() { + return Err(input.error("expected `query` or `non_query`")); + } let name: Ident = input.parse()?; // `(key: DefId)` @@ -84,7 +110,7 @@ fn parse(input: ParseStream<'_>) -> Result { doc_comments.push(doc_comment_from_desc(&modifiers.desc.expr_list)?); } - Ok(Query { doc_comments, modifiers, name, key_pat, key_ty, return_ty }) + Ok(QueryEntry::Query(Query { doc_comments, modifiers, name, key_pat, key_ty, return_ty })) } } @@ -375,9 +401,9 @@ macro_rules! doc_link { // macro producing a higher order macro that has all its token in the macro declaration we lose // any meaningful spans, resulting in rust-analyzer being unable to make the connection between // the query name and the corresponding providers field. The trick to fix this is to have - // `rustc_queries` emit a field access with the given name's span which allows it to successfully - // show references / go to definition to the corresponding provider assignment which is usually - // the more interesting place. + // `rustc_queries` emit a field access with the given name's span which allows it to + // successfully show references / go to definition to the corresponding provider assignment + // which is usually the more interesting place. let ra_hint = quote! { let crate::query::Providers { #name: _, .. }; }; @@ -393,9 +419,10 @@ fn #erased_name<'tcx>() #result { } pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { - let queries = parse_macro_input!(input as List); + let queries = parse_macro_input!(input as List); let mut query_stream = quote! {}; + let mut non_query_stream = quote! {}; let mut helpers = HelperTokenStreams::default(); let mut analyzer_stream = quote! {}; let mut errors = quote! {}; @@ -411,6 +438,18 @@ macro_rules! assert { } for query in queries.0 { + let query = match query { + QueryEntry::Query(query) => query, + QueryEntry::NonQuery(NonQuery { doc_comments, name }) => { + // Get the exceptional non-query case out of the way first. + non_query_stream.extend(quote! { + #(#doc_comments)* + #name, + }); + continue; + } + }; + let Query { doc_comments, name, key_ty, return_ty, modifiers, .. } = &query; // Normalize an absent return type into `-> ()` to make macro-rules parsing easier. @@ -486,24 +525,18 @@ fn #name(#key_ty) #return_ty, let HelperTokenStreams { description_fns_stream, cache_on_disk_if_fns_stream } = helpers; TokenStream::from(quote! { - /// Higher-order macro that invokes the specified macro with a prepared - /// list of all query signatures (including modifiers). - /// - /// This allows multiple simpler macros to each have access to the list - /// of queries. + /// Higher-order macro that invokes the specified macro with (a) a list of all query + /// signatures (including modifiers), and (b) a list of non-query names. This allows + /// multiple simpler macros to each have access to these lists. #[macro_export] macro_rules! rustc_with_all_queries { ( - // The macro to invoke once, on all queries (plus extras). + // The macro to invoke once, on all queries and non-queries. $macro:ident! - - // Within [], an optional list of extra "query" signatures to - // pass to the given macro, in addition to the actual queries. - $( [$($extra_fake_queries:tt)*] )? ) => { $macro! { - $( $($extra_fake_queries)* )? - #query_stream + queries { #query_stream } + non_queries { #non_query_stream } } } } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 599c84597a8b..f8b98b3991e7 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -270,15 +270,26 @@ impl StableOrd for WorkProductId { // Note: `$K` and `$V` are unused but present so this can be called by `rustc_with_all_queries`. macro_rules! define_dep_nodes { ( - $( - $(#[$attr:meta])* - [$($modifiers:tt)*] fn $variant:ident($K:ty) -> $V:ty, - )* + queries { + $( + $(#[$q_attr:meta])* + [$($modifiers:tt)*] + fn $q_name:ident($K:ty) -> $V:ty, + )* + } + non_queries { + $( + $(#[$nq_attr:meta])* + $nq_name:ident, + )* + } ) => { - #[macro_export] macro_rules! make_dep_kind_array { - ($mod:ident) => {[ $($mod::$variant()),* ]}; + ($mod:ident) => {[ + $( $mod::$nq_name(), )* + $( $mod::$q_name(), )* + ]}; } /// This enum serves as an index into arrays built by `make_dep_kind_array`. @@ -290,14 +301,18 @@ macro_rules! make_dep_kind_array { #[allow(non_camel_case_types)] #[repr(u16)] // Must be kept in sync with the rest of `DepKind`. pub enum DepKind { - $( $( #[$attr] )* $variant),* + $( $(#[$nq_attr])* $nq_name, )* + $( $(#[$q_attr])* $q_name, )* } // This computes the number of dep kind variants. Along the way, it sanity-checks that the // discriminants of the variants have been assigned consecutively from 0 so that they can // be used as a dense index, and that all discriminants fit in a `u16`. pub(crate) const DEP_KIND_NUM_VARIANTS: u16 = { - let deps = &[$(DepKind::$variant,)*]; + let deps = &[ + $(DepKind::$nq_name,)* + $(DepKind::$q_name,)* + ]; let mut i = 0; while i < deps.len() { if i != deps[i].as_usize() { @@ -311,7 +326,8 @@ pub enum DepKind { pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { - $( stringify!($variant) => Ok(self::DepKind::$variant), )* + $( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )* + $( stringify!($q_name) => Ok(self::DepKind::$q_name), )* _ => Err(()), } } @@ -320,27 +336,14 @@ pub(super) fn dep_kind_from_label_string(label: &str) -> Result { /// DepNode groups for tests. #[expect(non_upper_case_globals)] pub mod label_strs { - $( pub const $variant: &str = stringify!($variant); )* + $( pub const $nq_name: &str = stringify!($nq_name); )* + $( pub const $q_name: &str = stringify!($q_name); )* } }; } -// Create various data structures for each query, and also for a few things -// that aren't queries. The key and return types aren't used, hence the use of `()`. -rustc_with_all_queries!(define_dep_nodes![ - /// We use this for most things when incr. comp. is turned off. - [] fn Null(()) -> (), - /// We use this to create a forever-red node. - [] fn Red(()) -> (), - /// We use this to create a side effect node. - [] fn SideEffect(()) -> (), - /// We use this to create the anon node with zero dependencies. - [] fn AnonZeroDeps(()) -> (), - [] fn TraitSelect(()) -> (), - [] fn CompileCodegenUnit(()) -> (), - [] fn CompileMonoItem(()) -> (), - [] fn Metadata(()) -> (), -]); +// Create various data structures for each query, and also for a few things that aren't queries. +rustc_with_all_queries! { define_dep_nodes! } // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. // Be very careful changing this type signature! diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 0ff38a0f3604..92c0d6fe895b 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2771,6 +2771,23 @@ cache_on_disk_if { *cnum == LOCAL_CRATE } separate_provide_extern } + + //----------------------------------------------------------------------------- + // "Non-queries" are special dep kinds that are not queries. + //----------------------------------------------------------------------------- + + /// We use this for most things when incr. comp. is turned off. + non_query Null + /// We use this to create a forever-red node. + non_query Red + /// We use this to create a side effect node. + non_query SideEffect + /// We use this to create the anon node with zero dependencies. + non_query AnonZeroDeps + non_query TraitSelect + non_query CompileCodegenUnit + non_query CompileMonoItem + non_query Metadata } rustc_with_all_queries! { define_callbacks! } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 072e29aaa906..6b83c58a7bec 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -378,11 +378,15 @@ macro_rules! define_callbacks { ( // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that // `query_helper_param_ty!` can match on specific type names. - $( - $(#[$attr:meta])* - [$($modifiers:tt)*] - fn $name:ident($($K:tt)*) -> $V:ty, - )* + queries { + $( + $(#[$attr:meta])* + [$($modifiers:tt)*] + fn $name:ident($($K:tt)*) -> $V:ty, + )* + } + // Non-queries are unused here. + non_queries { $($_:tt)* } ) => { $( #[allow(unused_lifetimes)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f005e5541829..d972bab766c3 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -414,15 +414,20 @@ pub(crate) fn force_from_dep_node_inner<'tcx, Q: GetQueryVTable<'tcx>>( } } -// Note: `$K` and `$V` are unused but present so this can be called by `rustc_with_all_queries`. macro_rules! define_queries { ( - $( - $(#[$attr:meta])* - [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty, - )* + // Note: `$K` and `$V` are unused but present so this can be called by + // `rustc_with_all_queries`. + queries { + $( + $(#[$attr:meta])* + [$($modifiers:tt)*] + fn $name:ident($K:ty) -> $V:ty, + )* + } + // Non-queries are unused here. + non_queries { $($_:tt)* } ) => { - pub(crate) mod query_impl { $(pub(crate) mod $name { use super::super::*; use ::rustc_middle::query::erase::{self, Erased};