From b83aff6b2b4bf6639e328bbb5f2d4e1536eda105 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 16:32:03 +1100 Subject: [PATCH 1/3] Remove inner `query_impl` module from `define_queries!`. It's just an unnecessary level of additional nesting. #151893 did the same thing for the `define_callbacks` macro. --- compiler/rustc_query_impl/src/plumbing.rs | 33 ++++++++++------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 776d720f500bd..6f610383515ed 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -582,9 +582,8 @@ macro_rules! define_queries { [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty, )* ) => { - - pub(crate) mod query_impl { $(pub(crate) mod $name { - use super::super::*; + $(pub(crate) mod $name { + use super::*; use std::marker::PhantomData; use ::rustc_middle::query::erase::{self, Erased}; @@ -794,12 +793,8 @@ macro_rules! define_queries { encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex ) { - $crate::plumbing::encode_query_results::< - query_impl::$name::QueryType<'tcx>, - _, - _ - > ( - query_impl::$name::QueryType::query_dispatcher(tcx), + $crate::plumbing::encode_query_results::<$name::QueryType<'tcx>, _, _> ( + $name::QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), encoder, query_result_index, @@ -809,20 +804,20 @@ macro_rules! define_queries { pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { $crate::plumbing::query_key_hash_verify( - query_impl::$name::QueryType::query_dispatcher(tcx), + $name::QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), ) } - })*} + })* pub(crate) fn engine(incremental: bool) -> QueryEngine { if incremental { QueryEngine { - $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)* + $($name: $name::get_query_incr::__rust_end_short_backtrace,)* } } else { QueryEngine { - $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)* + $($name: $name::get_query_non_incr::__rust_end_short_backtrace,)* } } } @@ -830,7 +825,7 @@ macro_rules! define_queries { pub fn make_query_vtables<'tcx>() -> queries::PerQueryVTables<'tcx> { queries::PerQueryVTables { $( - $name: query_impl::$name::make_query_vtable(), + $name: $name::make_query_vtable(), )* } } @@ -846,12 +841,12 @@ macro_rules! define_queries { const PER_QUERY_GATHER_ACTIVE_JOBS_FNS: &[ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, require_complete: bool) -> Option<()> ] = &[ - $(query_impl::$name::gather_active_jobs),* + $($name::gather_active_jobs),* ]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache) - ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*]; + ] = &[$($name::alloc_self_profile_query_strings),*]; const ENCODE_QUERY_RESULTS: &[ Option fn( @@ -859,11 +854,11 @@ macro_rules! define_queries { &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex) > - ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*]; + ] = &[$(expand_if_cached!([$($modifiers)*], $name::encode_query_results)),*]; const QUERY_KEY_HASH_VERIFY: &[ for<'tcx> fn(TyCtxt<'tcx>) - ] = &[$(query_impl::$name::query_key_hash_verify),*]; + ] = &[$($name::query_key_hash_verify),*]; /// Module containing a named function for each dep kind (including queries) /// that creates a `DepKindVTable`. @@ -969,7 +964,7 @@ macro_rules! define_queries { } $(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { - use $crate::query_impl::$name::QueryType; + use super::$name::QueryType; $crate::plumbing::make_dep_kind_vtable_for_query::, _, _>( is_eval_always!([$($modifiers)*]), ) From 57413a5b0019577bb68cee74bb1f3cfd8601ddb7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 16:11:32 +1100 Subject: [PATCH 2/3] Improve formatting of the big query macros. Specifically `define_callbacks` and `define_queries`. These are big, complicated macros. If the top-level `$(..)*` repetitions are obvious it helps enormously with readability. --- compiler/rustc_middle/src/query/plumbing.rs | 357 ++++++++------- compiler/rustc_query_impl/src/plumbing.rs | 471 +++++++++++--------- 2 files changed, 448 insertions(+), 380 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 04a3ceb0918af..b51fec457a6ff 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -274,93 +274,97 @@ macro_rules! define_callbacks { ( $( $(#[$attr:meta])* - [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty, + [$($modifiers:tt)*] + fn $name:ident($($K:tt)*) -> $V:ty, )* ) => { - $(#[allow(unused_lifetimes)] pub mod $name { - use super::*; - use $crate::query::erase::{self, Erased}; - - pub type Key<'tcx> = $($K)*; - pub type Value<'tcx> = $V; - - pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); - - /// This type alias specifies the type returned from query providers and the type - /// used for decoding. For regular queries this is the declared returned type `V`, - /// but `arena_cache` will use `::Provided` instead. - pub type ProvidedValue<'tcx> = query_if_arena!( - [$($modifiers)*] - (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) - ($V) - ); - - /// This function takes `ProvidedValue` and converts it to an erased `Value` by - /// allocating it on an arena if the query has the `arena_cache` modifier. The - /// value is then erased and returned. This will happen when computing the query - /// using a provider or decoding a stored result. - #[inline(always)] - pub fn provided_to_erased<'tcx>( - _tcx: TyCtxt<'tcx>, - provided_value: ProvidedValue<'tcx>, - ) -> Erased> { - // Store the provided value in an arena and get a reference - // to it, for queries with `arena_cache`. - let value: Value<'tcx> = query_if_arena!([$($modifiers)*] - { - use $crate::query::arena_cached::ArenaCached; - - if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.query_system.arenas.$name.alloc(v), - provided_value, - ) - } else { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.arena.dropless.alloc(v), - provided_value, - ) - } - } - // Otherwise, the provided value is the value. - (provided_value) + $( + #[allow(unused_lifetimes)] + pub mod $name { + use super::*; + use $crate::query::erase::{self, Erased}; + + pub type Key<'tcx> = $($K)*; + pub type Value<'tcx> = $V; + + pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); + + /// This type alias specifies the type returned from query providers and the type + /// used for decoding. For regular queries this is the declared returned type `V`, + /// but `arena_cache` will use `::Provided` instead. + pub type ProvidedValue<'tcx> = query_if_arena!( + [$($modifiers)*] + (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) + ($V) ); - erase::erase_val(value) - } - pub type Storage<'tcx> = <$($K)* as $crate::query::Key>::Cache>; - - // Ensure that keys grow no larger than 88 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - const _: () = { - if size_of::>() > 88 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a key type `", - stringify!($($K)*), - "` that is too large" - )); - } - }; - - // Ensure that values grow no larger than 64 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - #[cfg(not(feature = "rustc_randomized_layouts"))] - const _: () = { - if size_of::>() > 64 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a value type `", - stringify!($V), - "` that is too large" - )); + /// This function takes `ProvidedValue` and converts it to an erased `Value` by + /// allocating it on an arena if the query has the `arena_cache` modifier. The + /// value is then erased and returned. This will happen when computing the query + /// using a provider or decoding a stored result. + #[inline(always)] + pub fn provided_to_erased<'tcx>( + _tcx: TyCtxt<'tcx>, + provided_value: ProvidedValue<'tcx>, + ) -> Erased> { + // Store the provided value in an arena and get a reference + // to it, for queries with `arena_cache`. + let value: Value<'tcx> = query_if_arena!([$($modifiers)*] + { + use $crate::query::arena_cached::ArenaCached; + + if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.query_system.arenas.$name.alloc(v), + provided_value, + ) + } else { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.arena.dropless.alloc(v), + provided_value, + ) + } + } + // Otherwise, the provided value is the value. + (provided_value) + ); + erase::erase_val(value) } - }; - })* + + pub type Storage<'tcx> = <$($K)* as $crate::query::Key>::Cache>; + + // Ensure that keys grow no larger than 88 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + const _: () = { + if size_of::>() > 88 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a key type `", + stringify!($($K)*), + "` that is too large" + )); + } + }; + + // Ensure that values grow no larger than 64 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + #[cfg(not(feature = "rustc_randomized_layouts"))] + const _: () = { + if size_of::>() > 64 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a value type `", + stringify!($V), + "` that is too large" + )); + } + }; + } + )* /// Holds per-query arenas for queries with the `arena_cache` modifier. #[derive(Default)] @@ -378,66 +382,74 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryCaches<'tcx> { - $($(#[$attr])* pub $name: $name::Storage<'tcx>,)* + $( + $(#[$attr])* pub $name: $name::Storage<'tcx>, + )* } impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> { - $($(#[$attr])* - #[inline(always)] - pub fn $name( - self, - key: query_helper_param_ty!($($K)*), - ) -> ensure_ok_result!([$($modifiers)*]) { - query_ensure_select!( - [$($modifiers)*] - self.tcx, - self.tcx.query_system.fns.engine.$name, - &self.tcx.query_system.caches.$name, - $crate::query::IntoQueryParam::into_query_param(key), - false, - ) - })* + $( + $(#[$attr])* + #[inline(always)] + pub fn $name( + self, + key: query_helper_param_ty!($($K)*), + ) -> ensure_ok_result!([$($modifiers)*]) { + query_ensure_select!( + [$($modifiers)*] + self.tcx, + self.tcx.query_system.fns.engine.$name, + &self.tcx.query_system.caches.$name, + $crate::query::IntoQueryParam::into_query_param(key), + false, + ) + } + )* } impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> { - $($(#[$attr])* - #[inline(always)] - pub fn $name(self, key: query_helper_param_ty!($($K)*)) { - crate::query::inner::query_ensure( - self.tcx, - self.tcx.query_system.fns.engine.$name, - &self.tcx.query_system.caches.$name, - $crate::query::IntoQueryParam::into_query_param(key), - true, - ); - })* + $( + $(#[$attr])* + #[inline(always)] + pub fn $name(self, key: query_helper_param_ty!($($K)*)) { + crate::query::inner::query_ensure( + self.tcx, + self.tcx.query_system.fns.engine.$name, + &self.tcx.query_system.caches.$name, + $crate::query::IntoQueryParam::into_query_param(key), + true, + ); + } + )* } impl<'tcx> TyCtxt<'tcx> { - $($(#[$attr])* - #[inline(always)] - #[must_use] - pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V - { - self.at(DUMMY_SP).$name(key) - })* + $( + $(#[$attr])* + #[inline(always)] + #[must_use] + pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V { + self.at(DUMMY_SP).$name(key) + } + )* } impl<'tcx> $crate::query::TyCtxtAt<'tcx> { - $($(#[$attr])* - #[inline(always)] - pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V - { - use $crate::query::{erase, inner}; - - erase::restore_val::<$V>(inner::query_get_at( - self.tcx, - self.tcx.query_system.fns.engine.$name, - &self.tcx.query_system.caches.$name, - self.span, - $crate::query::IntoQueryParam::into_query_param(key), - )) - })* + $( + $(#[$attr])* + #[inline(always)] + pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V { + use $crate::query::{erase, inner}; + + erase::restore_val::<$V>(inner::query_get_at( + self.tcx, + self.tcx.query_system.fns.engine.$name, + &self.tcx.query_system.caches.$name, + self.span, + $crate::query::IntoQueryParam::into_query_param(key), + )) + } + )* } /// Holds a `QueryVTable` for each query. @@ -457,20 +469,25 @@ macro_rules! define_callbacks { } pub struct Providers { - $(pub $name: for<'tcx> fn( - TyCtxt<'tcx>, - $name::LocalKey<'tcx>, - ) -> $name::ProvidedValue<'tcx>,)* + $( + pub $name: for<'tcx> + fn(TyCtxt<'tcx>, $name::LocalKey<'tcx>) -> $name::ProvidedValue<'tcx>, + )* } pub struct ExternProviders { - $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)* + $( + pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]), + )* } impl Default for Providers { fn default() -> Self { Providers { - $($name: |_, key| $crate::query::plumbing::default_query(stringify!($name), &key)),* + $( + $name: |_, key| + $crate::query::plumbing::default_query(stringify!($name), &key), + )* } } } @@ -478,7 +495,9 @@ macro_rules! define_callbacks { impl Default for ExternProviders { fn default() -> Self { ExternProviders { - $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)* + $( + $name: separate_provide_extern_default!([$($modifiers)*][$name]), + )* } } } @@ -494,39 +513,49 @@ macro_rules! define_callbacks { } pub struct QueryEngine { - $(pub $name: for<'tcx> fn( - TyCtxt<'tcx>, - Span, - $name::Key<'tcx>, - $crate::query::QueryMode, - ) -> Option<$crate::query::erase::Erased<$V>>,)* + $( + pub $name: for<'tcx> fn( + TyCtxt<'tcx>, + Span, + $name::Key<'tcx>, + $crate::query::QueryMode, + ) -> Option<$crate::query::erase::Erased<$V>>, + )* } }; } macro_rules! define_feedable { - ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - $(impl<'tcx, K: $crate::query::IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { - $(#[$attr])* - #[inline(always)] - pub fn $name(self, value: $name::ProvidedValue<'tcx>) { - let key = self.key().into_query_param(); - - let tcx = self.tcx; - let erased_value = $name::provided_to_erased(tcx, value); - - let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; - - $crate::query::inner::query_feed( - tcx, - dep_kind, - &tcx.query_system.query_vtables.$name, - &tcx.query_system.caches.$name, - key, - erased_value, - ); + ( + $( + $(#[$attr:meta])* + [$($modifiers:tt)*] + fn $name:ident($($K:tt)*) -> $V:ty, + )* + ) => { + $( + impl<'tcx, K: $crate::query::IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(#[$attr])* + #[inline(always)] + pub fn $name(self, value: $name::ProvidedValue<'tcx>) { + let key = self.key().into_query_param(); + + let tcx = self.tcx; + let erased_value = $name::provided_to_erased(tcx, value); + + let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; + + $crate::query::inner::query_feed( + tcx, + dep_kind, + &tcx.query_system.query_vtables.$name, + &tcx.query_system.caches.$name, + key, + erased_value, + ); + } } - })* + )* } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6f610383515ed..f326ba94dc1dc 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -579,236 +579,255 @@ macro_rules! define_queries { ( $( $(#[$attr:meta])* - [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty, + [$($modifiers:tt)*] + fn $name:ident($($K:tt)*) -> $V:ty, )* ) => { - $(pub(crate) mod $name { - use super::*; - use std::marker::PhantomData; - use ::rustc_middle::query::erase::{self, Erased}; - - pub(crate) mod get_query_incr { + $( + pub(crate) mod $name { use super::*; - - // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames - // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming - #[inline(never)] - pub(crate) fn __rust_end_short_backtrace<'tcx>( - tcx: TyCtxt<'tcx>, - span: Span, - key: queries::$name::Key<'tcx>, - mode: QueryMode, - ) -> Option>> { - #[cfg(debug_assertions)] - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - execution::get_query_incr( - QueryType::query_dispatcher(tcx), - QueryCtxt::new(tcx), - span, - key, - mode - ) + use std::marker::PhantomData; + use ::rustc_middle::query::erase::{self, Erased}; + + pub(crate) mod get_query_incr { + use super::*; + + // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the + // frames when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow + // duplicate naming. + #[inline(never)] + pub(crate) fn __rust_end_short_backtrace<'tcx>( + tcx: TyCtxt<'tcx>, + span: Span, + key: queries::$name::Key<'tcx>, + mode: QueryMode, + ) -> Option>> { + #[cfg(debug_assertions)] + let _guard = tracing::span!( + tracing::Level::TRACE, + stringify!($name), + ?key + ).entered(); + + execution::get_query_incr( + QueryType::query_dispatcher(tcx), + QueryCtxt::new(tcx), + span, + key, + mode + ) + } } - } - - pub(crate) mod get_query_non_incr { - use super::*; - #[inline(never)] - pub(crate) fn __rust_end_short_backtrace<'tcx>( - tcx: TyCtxt<'tcx>, - span: Span, - key: queries::$name::Key<'tcx>, - __mode: QueryMode, - ) -> Option>> { - Some(execution::get_query_non_incr( - QueryType::query_dispatcher(tcx), - QueryCtxt::new(tcx), - span, - key, - )) + pub(crate) mod get_query_non_incr { + use super::*; + + #[inline(never)] + pub(crate) fn __rust_end_short_backtrace<'tcx>( + tcx: TyCtxt<'tcx>, + span: Span, + key: queries::$name::Key<'tcx>, + __mode: QueryMode, + ) -> Option>> { + Some(execution::get_query_non_incr( + QueryType::query_dispatcher(tcx), + QueryCtxt::new(tcx), + span, + key, + )) + } } - } - /// Defines a `compute` function for this query, to be used as a - /// function pointer in the query's vtable. - mod compute_fn { - use super::*; - use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased}; - - /// This function would be named `compute`, but we also want it - /// to mark the boundaries of an omitted region in backtraces. - #[inline(never)] - pub(crate) fn __rust_begin_short_backtrace<'tcx>( - tcx: TyCtxt<'tcx>, - key: Key<'tcx>, - ) -> Erased> { - #[cfg(debug_assertions)] - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - - // Call the actual provider function for this query. - let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]); - rustc_middle::ty::print::with_reduced_queries!({ - tracing::trace!(?provided_value); - }); - - provided_to_erased(tcx, provided_value) + /// Defines a `compute` function for this query, to be used as a + /// function pointer in the query's vtable. + mod compute_fn { + use super::*; + use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased}; + + /// This function would be named `compute`, but we also want it + /// to mark the boundaries of an omitted region in backtraces. + #[inline(never)] + pub(crate) fn __rust_begin_short_backtrace<'tcx>( + tcx: TyCtxt<'tcx>, + key: Key<'tcx>, + ) -> Erased> { + #[cfg(debug_assertions)] + let _guard = tracing::span!( + tracing::Level::TRACE, + stringify!($name), + ?key + ).entered(); + + // Call the actual provider function for this query. + let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]); + rustc_middle::ty::print::with_reduced_queries!({ + tracing::trace!(?provided_value); + }); + + provided_to_erased(tcx, provided_value) + } } - } - pub(crate) fn make_query_vtable<'tcx>() - -> QueryVTable<'tcx, queries::$name::Storage<'tcx>> - { - QueryVTable { - name: stringify!($name), - eval_always: is_eval_always!([$($modifiers)*]), - dep_kind: dep_graph::dep_kinds::$name, - cycle_error_handling: cycle_error_handling!([$($modifiers)*]), - query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), - query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), - will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] { - Some(queries::cached::$name) - } { - None - }), - execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), - compute_fn: self::compute_fn::__rust_begin_short_backtrace, - try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { - Some(|tcx, key, prev_index, index| { - // Check the `cache_on_disk_if` condition for this key. - if !queries::cached::$name(tcx, key) { - return None; - } - - let value: queries::$name::ProvidedValue<'tcx> = - $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?; - - // Arena-alloc the value if appropriate, and erase it. - Some(queries::$name::provided_to_erased(tcx, value)) - }) - } { - None - }), - is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { - Some(|tcx, key, index| -> bool { - ::rustc_middle::queries::cached::$name(tcx, key) && - $crate::plumbing::loadable_from_disk(tcx, index) - }) - } { - None - }), - value_from_cycle_error: |tcx, cycle, guar| { - let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar); - erase::erase_val(result) - }, - hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]), - format_value: |value| format!("{:?}", erase::restore_val::>(*value)), - description_fn: $crate::queries::_description_fns::$name, + pub(crate) fn make_query_vtable<'tcx>() + -> QueryVTable<'tcx, queries::$name::Storage<'tcx>> + { + QueryVTable { + name: stringify!($name), + eval_always: is_eval_always!([$($modifiers)*]), + dep_kind: dep_graph::dep_kinds::$name, + cycle_error_handling: cycle_error_handling!([$($modifiers)*]), + query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), + query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), + will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] { + Some(queries::cached::$name) + } { + None + }), + execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), + compute_fn: self::compute_fn::__rust_begin_short_backtrace, + try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { + Some(|tcx, key, prev_index, index| { + // Check the `cache_on_disk_if` condition for this key. + if !queries::cached::$name(tcx, key) { + return None; + } + + let value: queries::$name::ProvidedValue<'tcx> = + $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?; + + // Arena-alloc the value if appropriate, and erase it. + Some(queries::$name::provided_to_erased(tcx, value)) + }) + } { + None + }), + is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { + Some(|tcx, key, index| -> bool { + ::rustc_middle::queries::cached::$name(tcx, key) && + $crate::plumbing::loadable_from_disk(tcx, index) + }) + } { + None + }), + value_from_cycle_error: |tcx, cycle, guar| { + let result: queries::$name::Value<'tcx> = + Value::from_cycle_error(tcx, cycle, guar); + erase::erase_val(result) + }, + hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]), + format_value: |value| format!( + "{:?}", + erase::restore_val::>(*value) + ), + description_fn: $crate::queries::_description_fns::$name, + } } - } - #[derive(Copy, Clone, Default)] - pub(crate) struct QueryType<'tcx> { - data: PhantomData<&'tcx ()> - } + #[derive(Copy, Clone, Default)] + pub(crate) struct QueryType<'tcx> { + data: PhantomData<&'tcx ()> + } - const FLAGS: QueryFlags = QueryFlags { - is_anon: is_anon!([$($modifiers)*]), - is_depth_limit: depth_limit!([$($modifiers)*]), - is_feedable: feedable!([$($modifiers)*]), - }; + const FLAGS: QueryFlags = QueryFlags { + is_anon: is_anon!([$($modifiers)*]), + is_depth_limit: depth_limit!([$($modifiers)*]), + is_feedable: feedable!([$($modifiers)*]), + }; - impl<'tcx> QueryDispatcherUnerased<'tcx, queries::$name::Storage<'tcx>, FLAGS> - for QueryType<'tcx> - { - type UnerasedValue = queries::$name::Value<'tcx>; + impl<'tcx> QueryDispatcherUnerased<'tcx, queries::$name::Storage<'tcx>, FLAGS> + for QueryType<'tcx> + { + type UnerasedValue = queries::$name::Value<'tcx>; - const NAME: &'static &'static str = &stringify!($name); + const NAME: &'static &'static str = &stringify!($name); - #[inline(always)] - fn query_dispatcher(tcx: TyCtxt<'tcx>) - -> SemiDynamicQueryDispatcher<'tcx, queries::$name::Storage<'tcx>, FLAGS> - { - SemiDynamicQueryDispatcher { - vtable: &tcx.query_system.query_vtables.$name, + #[inline(always)] + fn query_dispatcher(tcx: TyCtxt<'tcx>) + -> SemiDynamicQueryDispatcher<'tcx, queries::$name::Storage<'tcx>, FLAGS> + { + SemiDynamicQueryDispatcher { + vtable: &tcx.query_system.query_vtables.$name, + } } - } - #[inline(always)] - fn restore_val(value: as QueryCache>::Value) - -> Self::UnerasedValue - { - erase::restore_val::>(value) + #[inline(always)] + fn restore_val(value: as QueryCache>::Value) + -> Self::UnerasedValue + { + erase::restore_val::>(value) + } } - } - /// Internal per-query plumbing for collecting the set of active jobs for this query. - /// - /// Should only be called through `PER_QUERY_GATHER_ACTIVE_JOBS_FNS`. - pub(crate) fn gather_active_jobs<'tcx>( - tcx: TyCtxt<'tcx>, - qmap: &mut QueryMap<'tcx>, - require_complete: bool, - ) -> Option<()> { - let make_frame = |tcx: TyCtxt<'tcx>, key| { - let vtable = &tcx.query_system.query_vtables.$name; - $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key) - }; - - // Call `gather_active_jobs_inner` to do the actual work. - let res = crate::execution::gather_active_jobs_inner(&tcx.query_system.states.$name, - tcx, - make_frame, - qmap, - require_complete, - ); - - // this can be called during unwinding, and the function has a `try_`-prefix, so - // don't `unwrap()` here, just manually check for `None` and do best-effort error - // reporting. - if res.is_none() { - tracing::warn!( - "Failed to collect active jobs for query with name `{}`!", - stringify!($name) + /// Internal per-query plumbing for collecting the set of active jobs for this + /// query. + /// + /// Should only be called through `PER_QUERY_GATHER_ACTIVE_JOBS_FNS`. + pub(crate) fn gather_active_jobs<'tcx>( + tcx: TyCtxt<'tcx>, + qmap: &mut QueryMap<'tcx>, + require_complete: bool, + ) -> Option<()> { + let make_frame = |tcx: TyCtxt<'tcx>, key| { + let vtable = &tcx.query_system.query_vtables.$name; + $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key) + }; + + // Call `gather_active_jobs_inner` to do the actual work. + let res = crate::execution::gather_active_jobs_inner( + &tcx.query_system.states.$name, + tcx, + make_frame, + qmap, + require_complete, ); - } - res - } - pub(crate) fn alloc_self_profile_query_strings<'tcx>( - tcx: TyCtxt<'tcx>, - string_cache: &mut QueryKeyStringCache - ) { - $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( - tcx, - stringify!($name), - &tcx.query_system.caches.$name, - string_cache, - ) - } + // This can be called during unwinding, and the function has a `try_`-prefix, + // so don't `unwrap()` here, just manually check for `None` and do best-effort + // error reporting. + if res.is_none() { + tracing::warn!( + "Failed to collect active jobs for query with name `{}`!", + stringify!($name) + ); + } + res + } - item_if_cached! { [$($modifiers)*] { - pub(crate) fn encode_query_results<'tcx>( + pub(crate) fn alloc_self_profile_query_strings<'tcx>( tcx: TyCtxt<'tcx>, - encoder: &mut CacheEncoder<'_, 'tcx>, - query_result_index: &mut EncodedDepNodeIndex + string_cache: &mut QueryKeyStringCache ) { - $crate::plumbing::encode_query_results::<$name::QueryType<'tcx>, _, _> ( + $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( + tcx, + stringify!($name), + &tcx.query_system.caches.$name, + string_cache, + ) + } + + item_if_cached! { [$($modifiers)*] { + pub(crate) fn encode_query_results<'tcx>( + tcx: TyCtxt<'tcx>, + encoder: &mut CacheEncoder<'_, 'tcx>, + query_result_index: &mut EncodedDepNodeIndex + ) { + $crate::plumbing::encode_query_results::<$name::QueryType<'tcx>, _, _> ( + $name::QueryType::query_dispatcher(tcx), + QueryCtxt::new(tcx), + encoder, + query_result_index, + ) + } + }} + + pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { + $crate::plumbing::query_key_hash_verify( $name::QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), - encoder, - query_result_index, ) } - }} - - pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { - $crate::plumbing::query_key_hash_verify( - $name::QueryType::query_dispatcher(tcx), - QueryCtxt::new(tcx), - ) } - })* + )* pub(crate) fn engine(incremental: bool) -> QueryEngine { if incremental { @@ -841,12 +860,18 @@ macro_rules! define_queries { const PER_QUERY_GATHER_ACTIVE_JOBS_FNS: &[ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, require_complete: bool) -> Option<()> ] = &[ - $($name::gather_active_jobs),* + $( + $name::gather_active_jobs, + )* ]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache) - ] = &[$($name::alloc_self_profile_query_strings),*]; + ] = &[ + $( + $name::alloc_self_profile_query_strings, + )* + ]; const ENCODE_QUERY_RESULTS: &[ Option fn( @@ -854,11 +879,17 @@ macro_rules! define_queries { &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex) > - ] = &[$(expand_if_cached!([$($modifiers)*], $name::encode_query_results)),*]; + ] = &[ + $( + expand_if_cached!([$($modifiers)*], $name::encode_query_results), + )* + ]; - const QUERY_KEY_HASH_VERIFY: &[ - for<'tcx> fn(TyCtxt<'tcx>) - ] = &[$($name::query_key_hash_verify),*]; + const QUERY_KEY_HASH_VERIFY: &[for<'tcx> fn(TyCtxt<'tcx>)] = &[ + $( + $name::query_key_hash_verify, + )* + ]; /// Module containing a named function for each dep kind (including queries) /// that creates a `DepKindVTable`. @@ -876,7 +907,9 @@ macro_rules! define_queries { is_anon: false, is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)), + force_from_dep_node: Some( + |_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node) + ), try_load_from_on_disk_cache: None, name: &"Null", } @@ -888,7 +921,9 @@ macro_rules! define_queries { is_anon: false, is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)), + force_from_dep_node: Some( + |_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node) + ), try_load_from_on_disk_cache: None, name: &"Red", } @@ -963,15 +998,19 @@ macro_rules! define_queries { } } - $(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { - use super::$name::QueryType; - $crate::plumbing::make_dep_kind_vtable_for_query::, _, _>( - is_eval_always!([$($modifiers)*]), - ) - })* + $( + pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { + use super::$name::QueryType; + $crate::plumbing::make_dep_kind_vtable_for_query::, _, _>( + is_eval_always!([$($modifiers)*]), + ) + } + )* } - pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] { + pub fn make_dep_kind_vtables<'tcx>( + arena: &'tcx Arena<'tcx> + ) -> &'tcx [DepKindVTable<'tcx>] { arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors)) } } From bceb3c011db5bf1589ac44799c788779e09a2731 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 17:08:33 +1100 Subject: [PATCH 3/3] Remove lifetime from `QueryType`. It's a unit type used for trait stuff, it doesn't need a lifetime. (Unless there's some weird variance thing I'm unaware of, but it compiles fine, so I think it should be ok.) --- compiler/rustc_query_impl/src/plumbing.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f326ba94dc1dc..214ab48ccf549 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -586,7 +586,6 @@ macro_rules! define_queries { $( pub(crate) mod $name { use super::*; - use std::marker::PhantomData; use ::rustc_middle::query::erase::{self, Erased}; pub(crate) mod get_query_incr { @@ -724,9 +723,7 @@ macro_rules! define_queries { } #[derive(Copy, Clone, Default)] - pub(crate) struct QueryType<'tcx> { - data: PhantomData<&'tcx ()> - } + pub(crate) struct QueryType; const FLAGS: QueryFlags = QueryFlags { is_anon: is_anon!([$($modifiers)*]), @@ -735,7 +732,7 @@ macro_rules! define_queries { }; impl<'tcx> QueryDispatcherUnerased<'tcx, queries::$name::Storage<'tcx>, FLAGS> - for QueryType<'tcx> + for QueryType { type UnerasedValue = queries::$name::Value<'tcx>; @@ -811,7 +808,7 @@ macro_rules! define_queries { encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex ) { - $crate::plumbing::encode_query_results::<$name::QueryType<'tcx>, _, _> ( + $crate::plumbing::encode_query_results::<$name::QueryType, _, _> ( $name::QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), encoder, @@ -1001,7 +998,7 @@ macro_rules! define_queries { $( pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { use super::$name::QueryType; - $crate::plumbing::make_dep_kind_vtable_for_query::, _, _>( + $crate::plumbing::make_dep_kind_vtable_for_query::( is_eval_always!([$($modifiers)*]), ) }