mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Make non-queries available to rustc_with_all_queries.
`rustc_with_all_queries` currently provides information about all queries. Also, a caller can provide an ad hoc list of extra non-queries. This is used by `define_queries` for non-query dep kinds: `Null`, `Red`, etc. This is pretty hacky. This commit changes `rustc_with_all_queries` so that the non-queries information is available to all callers. (Some callers ignore the non-query information.) This is done by adding `non_query` entries to the primary list of queries in `rustc_queries!`.
This commit is contained in:
@@ -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<Attribute>,
|
||||
name: Ident,
|
||||
}
|
||||
|
||||
enum QueryEntry {
|
||||
Query(Query),
|
||||
NonQuery(NonQuery),
|
||||
}
|
||||
|
||||
impl Parse for QueryEntry {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let mut doc_comments = check_attributes(input.call(Attribute::parse_outer)?)?;
|
||||
|
||||
// Try the non-query case first.
|
||||
if input.parse::<kw::non_query>().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::<kw::query>()?;
|
||||
if input.parse::<kw::query>().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<Self> {
|
||||
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<Query>);
|
||||
let queries = parse_macro_input!(input as List<QueryEntry>);
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<DepKind, ()> {
|
||||
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<DepKind, ()> {
|
||||
/// 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!
|
||||
|
||||
@@ -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! }
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user