diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 1ffbdfbf11875..5b583796c1756 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -324,11 +324,12 @@ impl StableOrd for WorkProductId { const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } +// 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:tt)*) -> $V:ty, + [$($modifiers:tt)*] fn $variant:ident($K:ty) -> $V:ty, )* ) => { @@ -382,20 +383,20 @@ macro_rules! define_dep_nodes { } // Create various data structures for each query, and also for a few things -// that aren't queries. +// 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() -> (), + [] fn Null(()) -> (), /// We use this to create a forever-red node. - [] fn Red() -> (), + [] fn Red(()) -> (), /// We use this to create a side effect node. - [] fn SideEffect() -> (), + [] fn SideEffect(()) -> (), /// We use this to create the anon node with zero dependencies. - [] fn AnonZeroDeps() -> (), - [] fn TraitSelect() -> (), - [] fn CompileCodegenUnit() -> (), - [] fn CompileMonoItem() -> (), - [] fn Metadata() -> (), + [] fn AnonZeroDeps(()) -> (), + [] fn TraitSelect(()) -> (), + [] fn CompileCodegenUnit(()) -> (), + [] fn CompileMonoItem(()) -> (), + [] fn Metadata(()) -> (), ]); // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 03618ee6acd46..a48fc8908f498 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -262,181 +262,146 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Calls either `query_ensure` or `query_ensure_error_guaranteed`, depending -/// on whether the list of modifiers contains `return_result_from_ensure_ok`. -macro_rules! query_ensure_select { - ([]$($args:tt)*) => { - crate::query::inner::query_ensure($($args)*) - }; - ([(return_result_from_ensure_ok) $($rest:tt)*]$($args:tt)*) => { - crate::query::inner::query_ensure_error_guaranteed($($args)*) - }; - ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { - query_ensure_select!([$($modifiers)*]$($args)*) - }; -} - macro_rules! query_helper_param_ty { (DefId) => { impl $crate::query::IntoQueryParam }; (LocalDefId) => { impl $crate::query::IntoQueryParam }; ($K:ty) => { $K }; } -macro_rules! query_if_arena { - ([] $arena:tt $no_arena:tt) => { - $no_arena - }; - ([(arena_cache) $($rest:tt)*] $arena:tt $no_arena:tt) => { - $arena - }; - ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { - query_if_arena!([$($modifiers)*]$($args)*) +// Expands to `$yes` if the `arena_cache` modifier is present, `$no` otherwise. +macro_rules! if_arena_cache { + ([] $then:tt $no:tt) => { $no }; + ([(arena_cache) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes }; + ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { + if_arena_cache!([$($modifiers)*] $yes $no) }; } -/// If `separate_provide_extern`, then the key can be projected to its -/// local key via `<$K as AsLocalKey>::LocalKey`. -macro_rules! local_key_if_separate_extern { - ([] $($K:tt)*) => { - $($K)* - }; - ([(separate_provide_extern) $($rest:tt)*] $($K:tt)*) => { - <$($K)* as $crate::query::AsLocalKey>::LocalKey - }; - ([$other:tt $($modifiers:tt)*] $($K:tt)*) => { - local_key_if_separate_extern!([$($modifiers)*] $($K)*) +// Expands to `$yes` if the `separate_provide_extern` modifier is present, `$no` otherwise. +macro_rules! if_separate_provide_extern { + ([] $then:tt $no:tt) => { $no }; + ([(separate_provide_extern) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes }; + ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { + if_separate_provide_extern!([$($modifiers)*] $yes $no) }; } -macro_rules! separate_provide_extern_decl { - ([][$name:ident]) => { - () - }; - ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { - for<'tcx> fn( - TyCtxt<'tcx>, - $name::Key<'tcx>, - ) -> $name::ProvidedValue<'tcx> - }; - ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { - separate_provide_extern_decl!([$($modifiers)*][$($args)*]) - }; -} - -macro_rules! ensure_ok_result { - ( [] ) => { - () - }; - ( [(return_result_from_ensure_ok) $($rest:tt)*] ) => { - Result<(), ErrorGuaranteed> - }; - ( [$other:tt $($modifiers:tt)*] ) => { - ensure_ok_result!( [$($modifiers)*] ) - }; -} - -macro_rules! separate_provide_extern_default { - ([][$name:ident]) => { - () - }; - ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { - |_, key| $crate::query::plumbing::default_extern_query(stringify!($name), &key) - }; - ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { - separate_provide_extern_default!([$($modifiers)*][$($args)*]) +// Expands to `$yes` if the `return_result_from_ensure_ok` modifier is present, `$no` otherwise. +macro_rules! if_return_result_from_ensure_ok { + ([] $then:tt $no:tt) => { $no }; + ([(return_result_from_ensure_ok) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes }; + ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { + if_return_result_from_ensure_ok!([$($modifiers)*] $yes $no) }; } 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, + [$($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 helper function takes a value returned by the query provider - /// (or loaded from disk, or supplied by query feeding), allocates - /// it in an arena if requested by the `arena_cache` modifier, and - /// then returns an erased copy of it. - #[inline(always)] - pub fn provided_to_erased<'tcx>( - tcx: TyCtxt<'tcx>, - provided_value: ProvidedValue<'tcx>, - ) -> Erased> { - // For queries with the `arena_cache` modifier, store the - // provided value in an arena and get a reference to it. - let value: Value<'tcx> = query_if_arena!([$($modifiers)*] { - <$V as $crate::query::arena_cached::ArenaCached>::alloc_in_arena( - tcx, - &tcx.query_system.arenas.$name, - provided_value, - ) - } { - // Otherwise, the provided value is the value (and `tcx` is unused). - let _ = tcx; - provided_value - }); - erase::erase_val(value) - } + $( + #[allow(unused_lifetimes)] + pub mod $name { + use super::*; + use $crate::query::erase::{self, Erased}; - 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" - )); + pub type Key<'tcx> = $($K)*; + pub type Value<'tcx> = $V; + + pub type LocalKey<'tcx> = if_separate_provide_extern!( + [$($modifiers)*] + ( as $crate::query::AsLocalKey>::LocalKey) + (Key<'tcx>) + ); + + /// 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> = if_arena_cache!( + [$($modifiers)*] + ( as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) + (Value<'tcx>) + ); + + /// This helper function takes a value returned by the query provider + /// (or loaded from disk, or supplied by query feeding), allocates + /// it in an arena if requested by the `arena_cache` modifier, and + /// then returns an erased copy of it. + #[inline(always)] + pub fn provided_to_erased<'tcx>( + tcx: TyCtxt<'tcx>, + provided_value: ProvidedValue<'tcx>, + ) -> Erased> { + // For queries with the `arena_cache` modifier, store the + // provided value in an arena and get a reference to it. + let value: Value<'tcx> = if_arena_cache!( + [$($modifiers)*] + { + as $crate::query::arena_cached::ArenaCached>:: + alloc_in_arena + ( + tcx, + &tcx.query_system.arenas.$name, + provided_value, + ) + } + { + // Otherwise, the provided value is the value (and `tcx` is unused). + let _ = tcx; + provided_value + } + ); + erase::erase_val(value) } - }; - })* + + pub type Storage<'tcx> = + 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)] pub struct QueryArenas<'tcx> { $( - $(#[$attr])* - pub $name: query_if_arena!([$($modifiers)*] + pub $name: if_arena_cache!( + [$($modifiers)*] // Use the `ArenaCached` helper trait to determine the arena's value type. (TypedArena<<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated>) // No arena for this query, so the field type is `()`. @@ -447,66 +412,81 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryCaches<'tcx> { - $($(#[$attr])* pub $name: $name::Storage<'tcx>,)* + $( + 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!( + $( + $(#[$attr])* + #[inline(always)] + pub fn $name( + self, + key: query_helper_param_ty!($($K)*), + ) -> if_return_result_from_ensure_ok!( [$($modifiers)*] - self.tcx, - self.tcx.query_system.fns.engine.$name, - &self.tcx.query_system.caches.$name, - $crate::query::IntoQueryParam::into_query_param(key), - false, - ) - })* + (Result<(), ErrorGuaranteed>) + () + ) { + if_return_result_from_ensure_ok!( + [$($modifiers)*] + (crate::query::inner::query_ensure_error_guaranteed) + (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), + 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. @@ -521,7 +501,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: $crate::query::QueryState<'tcx, $($K)*>, + pub $name: $crate::query::QueryState<'tcx, $name::Key<'tcx>>, )* } @@ -537,13 +517,23 @@ macro_rules! define_callbacks { } pub struct ExternProviders { - $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)* + $( + pub $name: if_separate_provide_extern!( + [$($modifiers)*] + (for<'tcx> fn(TyCtxt<'tcx>, $name::Key<'tcx>) -> $name::ProvidedValue<'tcx>) + () + ), + )* } 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) + }, + )* } } } @@ -551,7 +541,16 @@ macro_rules! define_callbacks { impl Default for ExternProviders { fn default() -> Self { ExternProviders { - $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)* + $( + $name: if_separate_provide_extern!( + [$($modifiers)*] + (|_, key| $crate::query::plumbing::default_extern_query( + stringify!($name), + &key + )) + () + ), + )* } } } @@ -567,37 +566,48 @@ 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>>, + )* } }; } +// Note: `$V` is unused but present so this can be called by `rustc_with_all_queries`. 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); - - $crate::query::inner::query_feed( - tcx, - dep_graph::DepKind::$name, - &tcx.query_system.query_vtables.$name, - &tcx.query_system.caches.$name, - key, - erased_value, - ); + ( + $( + $(#[$attr:meta])* + [$($modifiers:tt)*] + fn $name:ident($K:ty) -> $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); + + $crate::query::inner::query_feed( + tcx, + dep_graph::DepKind::$name, + &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 1ed601aae3562..31e81a62d5270 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -471,13 +471,12 @@ pub(crate) fn force_from_dep_node_inner<'tcx, C: QueryCache, const FLAGS: QueryF } } -// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros -// invoked by `rustc_with_all_queries`. +// 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:tt)*) -> $V:ty, + [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty, )* ) => {