From 1d678f6b0859ea25c2abc22eb4104a025a5737e4 Mon Sep 17 00:00:00 2001 From: Deepesh Varatharajan Date: Mon, 2 Mar 2026 04:22:23 -0800 Subject: [PATCH 1/2] Update call-llvm-intrinsics test for Rust 1.94.0 IR and multi-target CI Rust 1.94 now passes constants directly to llvm.sqrt.f32 instead of storing/loading via the stack. - Updated the FileCheck pattern to match the new IR: // CHECK: call float @llvm.sqrt.f32(float 4.000000e+00) The test intent is unchanged: it still ensures the intrinsic is emitted as a 'call' (not 'invoke'). - Removed unnecessary local variables and Drop usage to work in `#![no_core]` mode with minicore. - Added required crate attributes: #![feature(no_core, lang_items)] #![no_std] #![no_core] - Replaced `//@ only-riscv64` (host-based execution) with explicit revisions for: riscv32gc-unknown-linux-gnu riscv64gc-unknown-linux-gnu This ensures deterministic multi-target coverage in CI without relying on the host architecture. - Added `//@ needs-llvm-components: riscv` and `//@ min-llvm-version: 21` for CI compatibility. Signed-off-by: Deepesh Varatharajan --- .../riscv-abi/call-llvm-intrinsics.rs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/codegen-llvm/riscv-abi/call-llvm-intrinsics.rs b/tests/codegen-llvm/riscv-abi/call-llvm-intrinsics.rs index e72a649a530a8..fb520d38df3ca 100644 --- a/tests/codegen-llvm/riscv-abi/call-llvm-intrinsics.rs +++ b/tests/codegen-llvm/riscv-abi/call-llvm-intrinsics.rs @@ -1,17 +1,20 @@ +//@ add-minicore //@ compile-flags: -C no-prepopulate-passes - -//@ only-riscv64 +//@ revisions: riscv32gc riscv64gc +//@ [riscv32gc] compile-flags: --target riscv32gc-unknown-linux-gnu +//@ [riscv32gc] needs-llvm-components: riscv +//@ [riscv64gc] compile-flags: --target riscv64gc-unknown-linux-gnu +//@ [riscv64gc] needs-llvm-components: riscv +//@ min-llvm-version: 21 #![feature(link_llvm_intrinsics)] +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] #![crate_type = "lib"] -struct A; - -impl Drop for A { - fn drop(&mut self) { - println!("A"); - } -} +extern crate minicore; +use minicore::*; extern "C" { #[link_name = "llvm.sqrt.f32"] @@ -19,12 +22,9 @@ extern "C" { } pub fn do_call() { - let _a = A; - unsafe { // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them - // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4 - // CHECK: call float @llvm.sqrt.f32(float %{{.}} + // CHECK: call float @llvm.sqrt.f32(float 4.000000e+00) sqrt(4.0); } } From 083b5db4766dc02e939e3aa92182dbad37d05b4b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 3 Mar 2026 14:06:03 +1100 Subject: [PATCH 2/2] Make `rustc_with_all_queries!` pass query modifiers as named values --- compiler/rustc_macros/src/query.rs | 155 ++++++------ .../rustc_middle/src/dep_graph/dep_node.rs | 6 +- compiler/rustc_middle/src/query/plumbing.rs | 212 +++++++--------- .../rustc_query_impl/src/dep_kind_vtables.rs | 22 +- compiler/rustc_query_impl/src/plumbing.rs | 237 ++++++------------ 5 files changed, 260 insertions(+), 372 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 721cc7fe4d9b3..0a741d32ed61d 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -137,54 +137,23 @@ struct CacheOnDiskIf { block: Block, } +/// See `rustc_middle::query::modifiers` for documentation of each query modifier. struct QueryModifiers { - /// The description of the query. - desc: Desc, - - /// Use this type for the in-memory cache. + // tidy-alphabetical-start + anon: Option, arena_cache: Option, - - /// Cache the query to disk if the `Block` returns true. cache_on_disk_if: Option, - - /// A cycle error for this query aborting the compilation with a fatal error. - cycle_fatal: Option, - - /// A cycle error results in a delay_bug call cycle_delay_bug: Option, - - /// A cycle error results in a stashed cycle error that can be unstashed and canceled later + cycle_fatal: Option, cycle_stash: Option, - - /// Don't hash the result, instead just mark a query red if it runs - no_hash: Option, - - /// Generate a dep node based on the dependencies of the query - anon: Option, - - /// Always evaluate the query, ignoring its dependencies - eval_always: Option, - - /// Whether the query has a call depth limit depth_limit: Option, - - /// Use a separate query provider for local and extern crates - separate_provide_extern: Option, - - /// Generate a `feed` method to set the query's value from another query. + desc: Desc, + eval_always: Option, feedable: Option, - - /// When this query is called via `tcx.ensure_ok()`, it returns - /// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to - /// be executed, and that execution returns an error, the error result is - /// returned to the caller. - /// - /// If execution is skipped, a synthetic `Ok(())` is returned, on the - /// assumption that a query with all-green inputs must have succeeded. - /// - /// Can only be applied to queries with a return value of - /// `Result<_, ErrorGuaranteed>`. + no_hash: Option, return_result_from_ensure_ok: Option, + separate_provide_extern: Option, + // tidy-alphabetical-end } fn parse_query_modifiers(input: ParseStream<'_>) -> Result { @@ -272,6 +241,68 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { }) } +fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macro2::TokenStream { + let QueryModifiers { + // tidy-alphabetical-start + anon, + arena_cache, + cache_on_disk_if, + cycle_delay_bug, + cycle_fatal, + cycle_stash, + depth_limit, + desc: _, + eval_always, + feedable, + no_hash, + return_result_from_ensure_ok, + separate_provide_extern, + // tidy-alphabetical-end + } = modifiers; + + let anon = anon.is_some(); + let arena_cache = arena_cache.is_some(); + let cache_on_disk = cache_on_disk_if.is_some(); + + let cycle_error_handling = if cycle_delay_bug.is_some() { + quote! { DelayBug } + } else if cycle_fatal.is_some() { + quote! { Fatal } + } else if cycle_stash.is_some() { + quote! { Stash } + } else { + quote! { Error } + }; + + let depth_limit = depth_limit.is_some(); + let eval_always = eval_always.is_some(); + let feedable = feedable.is_some(); + let no_hash = no_hash.is_some(); + let return_result_from_ensure_ok = return_result_from_ensure_ok.is_some(); + let separate_provide_extern = separate_provide_extern.is_some(); + + // Giving an input span to the modifier names in the modifier list seems + // to give slightly more helpful errors when one of the callback macros + // fails to parse the modifier list. + let query_name_span = query.name.span(); + quote_spanned! { + query_name_span => + // Search for (QMODLIST) to find all occurrences of this query modifier list. + // tidy-alphabetical-start + anon: #anon, + arena_cache: #arena_cache, + cache_on_disk: #cache_on_disk, + cycle_error_handling: #cycle_error_handling, + depth_limit: #depth_limit, + eval_always: #eval_always, + feedable: #feedable, + no_hash: #no_hash, + return_result_from_ensure_ok: #return_result_from_ensure_ok, + separate_provide_extern: #separate_provide_extern, + // tidy-alphabetical-end + } +} + fn doc_comment_from_desc(list: &Punctuated) -> Result { use ::syn::*; let mut iter = list.iter(); @@ -458,51 +489,13 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { ReturnType::Type(..) => quote! { #return_ty }, }; - let mut modifiers_out = vec![]; - - macro_rules! passthrough { - ( $( $modifier:ident ),+ $(,)? ) => { - $( if let Some($modifier) = &modifiers.$modifier { - modifiers_out.push(quote! { (#$modifier) }); - }; )+ - } - } - - passthrough!( - arena_cache, - cycle_fatal, - cycle_delay_bug, - cycle_stash, - no_hash, - anon, - eval_always, - feedable, - depth_limit, - separate_provide_extern, - return_result_from_ensure_ok, - ); - - // If there was a `cache_on_disk_if` modifier in the real input, pass - // on a synthetic `(cache_on_disk)` modifier that can be inspected by - // macro-rules macros. - if modifiers.cache_on_disk_if.is_some() { - modifiers_out.push(quote! { (cache_on_disk) }); - } - - // This uses the span of the query definition for the commas, - // which can be important if we later encounter any ambiguity - // errors with any of the numerous macro_rules! macros that - // we use. Using the call-site span would result in a span pointing - // at the entire `rustc_queries!` invocation, which wouldn't - // be very useful. - let span = name.span(); - let modifiers_stream = quote_spanned! { span => #(#modifiers_out),* }; + let modifiers_stream = make_modifiers_stream(&query, modifiers); // Add the query to the group query_stream.extend(quote! { #(#doc_comments)* - [#modifiers_stream] - fn #name(#key_ty) #return_ty, + fn #name(#key_ty) #return_ty + { #modifiers_stream } }); if let Some(feedable) = &modifiers.feedable { diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 7efa013c3d999..6f85dba23dd49 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -268,8 +268,10 @@ macro_rules! define_dep_nodes { queries { $( $(#[$q_attr:meta])* - [$($modifiers:tt)*] - fn $q_name:ident($K:ty) -> $V:ty, + fn $q_name:ident($K:ty) -> $V:ty + // Search for (QMODLIST) to find all occurrences of this query modifier list. + // Query modifiers are currently not used here, so skip the whole list. + { $($modifiers:tt)* } )* } non_queries { diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index ff6d87298028f..815c8a1baab61 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -333,44 +333,6 @@ macro_rules! query_helper_param_ty { ($K:ty) => { $K }; } -// 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) - }; -} - -// 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) - }; -} - -// 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) - }; -} - -// Expands to `$item` if the `feedable` modifier is present. -macro_rules! item_if_feedable { - ([] $($item:tt)*) => {}; - ([(feedable) $($rest:tt)*] $($item:tt)*) => { - $($item)* - }; - ([$other:tt $($modifiers:tt)*] $($item:tt)*) => { - item_if_feedable! { [$($modifiers)*] $($item)* } - }; -} - macro_rules! define_callbacks { ( // You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that @@ -378,8 +340,20 @@ macro_rules! define_callbacks { queries { $( $(#[$attr:meta])* - [$($modifiers:tt)*] - fn $name:ident($($K:tt)*) -> $V:ty, + fn $name:ident($($K:tt)*) -> $V:ty + { + // Search for (QMODLIST) to find all occurrences of this query modifier list. + anon: $anon:literal, + arena_cache: $arena_cache:literal, + cache_on_disk: $cache_on_disk:literal, + cycle_error_handling: $cycle_error_handling:ident, + depth_limit: $depth_limit:literal, + eval_always: $eval_always:literal, + feedable: $feedable:literal, + no_hash: $no_hash:literal, + return_result_from_ensure_ok: $return_result_from_ensure_ok:literal, + separate_provide_extern: $separate_provide_extern:literal, + } )* } // Non-queries are unused here. @@ -394,20 +368,31 @@ macro_rules! define_callbacks { pub type Key<'tcx> = $($K)*; pub type Value<'tcx> = $V; - pub type LocalKey<'tcx> = if_separate_provide_extern!( - [$($modifiers)*] - ( as $crate::query::AsLocalQueryKey>::LocalQueryKey) - (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>) - ); + /// Key type used by provider functions in `local_providers`. + /// This query has the `separate_provide_extern` modifier. + #[cfg($separate_provide_extern)] + pub type LocalKey<'tcx> = + as $crate::query::AsLocalQueryKey>::LocalQueryKey; + /// Key type used by provider functions in `local_providers`. + #[cfg(not($separate_provide_extern))] + pub type LocalKey<'tcx> = Key<'tcx>; + + /// Return type of the `.ensure_ok()` method for this query, + /// which has the `return_result_from_ensure_ok` modifier. + #[cfg($return_result_from_ensure_ok)] + pub type EnsureOkReturnType = Result<(), rustc_errors::ErrorGuaranteed>; + /// Return type of the `.ensure_ok()` method for this query, + /// which does _not_ have the `return_result_from_ensure_ok` modifier. + #[cfg(not($return_result_from_ensure_ok))] + pub type EnsureOkReturnType = (); + + /// Type returned from query providers and loaded from disk-cache. + #[cfg($arena_cache)] + pub type ProvidedValue<'tcx> = + as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided; + /// Type returned from query providers and loaded from disk-cache. + #[cfg(not($arena_cache))] + pub type ProvidedValue<'tcx> = Value<'tcx>; /// This helper function takes a value returned by the query provider /// (or loaded from disk, or supplied by query feeding), allocates @@ -420,23 +405,23 @@ macro_rules! define_callbacks { ) -> 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 - } - ); + #[cfg($arena_cache)] + let value: Value<'tcx> = { + use $crate::query::arena_cached::ArenaCached; + as ArenaCached>::alloc_in_arena( + tcx, + &tcx.query_system.arenas.$name, + provided_value, + ) + }; + + // Otherwise, the provided value is the value (and `tcx` is unused). + #[cfg(not($arena_cache))] + let value: Value<'tcx> = { + let _ = tcx; + provided_value + }; + erase::erase_val(value) } @@ -480,13 +465,11 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryArenas<'tcx> { $( - 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 `()`. - () - ), + // Use the `ArenaCached` helper trait to determine the arena's value type. + #[cfg($arena_cache)] + pub $name: TypedArena< + <$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated, + >, )* } @@ -497,16 +480,14 @@ macro_rules! define_callbacks { pub fn $name( self, key: query_helper_param_ty!($($K)*), - ) -> if_return_result_from_ensure_ok!( - [$($modifiers)*] - (Result<(), ErrorGuaranteed>) - () - ) { - if_return_result_from_ensure_ok!( - [$($modifiers)*] - (crate::query::inner::query_ensure_error_guaranteed) - (crate::query::inner::query_ensure) - )( + ) -> $crate::queries::$name::EnsureOkReturnType { + + #[cfg($return_result_from_ensure_ok)] + let ensure_fn = crate::query::inner::query_ensure_error_guaranteed; + #[cfg(not($return_result_from_ensure_ok))] + let ensure_fn = crate::query::inner::query_ensure; + + ensure_fn( self.tcx, &self.tcx.query_system.query_vtables.$name, $crate::query::IntoQueryParam::into_query_param(key), @@ -560,24 +541,22 @@ macro_rules! define_callbacks { } $( - item_if_feedable! { - [$($modifiers)*] - impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy> - TyCtxtFeed<'tcx, K> - { - $(#[$attr])* - #[inline(always)] - pub fn $name(self, value: $name::ProvidedValue<'tcx>) { - let key = self.key().into_query_param(); - let erased_value = $name::provided_to_erased(self.tcx, value); - $crate::query::inner::query_feed( - self.tcx, - dep_graph::DepKind::$name, - &self.tcx.query_system.query_vtables.$name, - key, - erased_value, - ); - } + #[cfg($feedable)] + impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy> + TyCtxtFeed<'tcx, K> + { + $(#[$attr])* + #[inline(always)] + pub fn $name(self, value: $name::ProvidedValue<'tcx>) { + let key = self.key().into_query_param(); + let erased_value = $name::provided_to_erased(self.tcx, value); + $crate::query::inner::query_feed( + self.tcx, + dep_graph::DepKind::$name, + &self.tcx.query_system.query_vtables.$name, + key, + erased_value, + ); } } )* @@ -602,11 +581,11 @@ macro_rules! define_callbacks { pub struct ExternProviders { $( - pub $name: if_separate_provide_extern!( - [$($modifiers)*] - (for<'tcx> fn(TyCtxt<'tcx>, $name::Key<'tcx>) -> $name::ProvidedValue<'tcx>) - () - ), + #[cfg($separate_provide_extern)] + pub $name: for<'tcx> fn( + TyCtxt<'tcx>, + $name::Key<'tcx>, + ) -> $name::ProvidedValue<'tcx>, )* } @@ -626,13 +605,10 @@ macro_rules! define_callbacks { fn default() -> Self { ExternProviders { $( - $name: if_separate_provide_extern!( - [$($modifiers)*] - (|_, key| $crate::query::plumbing::default_extern_query( - stringify!($name), - &key - )) - () + #[cfg($separate_provide_extern)] + $name: |_, key| $crate::query::plumbing::default_extern_query( + stringify!($name), + &key, ), )* } diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index ceddef5385a58..0f3ef34d936a4 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -130,8 +130,20 @@ macro_rules! define_dep_kind_vtables { queries { $( $(#[$attr:meta])* - [$($modifiers:tt)*] - fn $name:ident($K:ty) -> $V:ty, + fn $name:ident($K:ty) -> $V:ty + { + // Search for (QMODLIST) to find all occurrences of this query modifier list. + anon: $anon:literal, + arena_cache: $arena_cache:literal, + cache_on_disk: $cache_on_disk:literal, + cycle_error_handling: $cycle_error_handling:ident, + depth_limit: $depth_limit:literal, + eval_always: $eval_always:literal, + feedable: $feedable:literal, + no_hash: $no_hash:literal, + return_result_from_ensure_ok: $return_result_from_ensure_ok:literal, + separate_provide_extern: $separate_provide_extern:literal, + } )* } non_queries { @@ -154,9 +166,9 @@ macro_rules! define_dep_kind_vtables { $crate::dep_kind_vtables::make_dep_kind_vtable_for_query::< $crate::query_impl::$name::VTableGetter, >( - is_anon!([$($modifiers)*]), - if_cache_on_disk!([$($modifiers)*] true false), - is_eval_always!([$($modifiers)*]), + $anon, + $cache_on_disk, + $eval_always, ) ),* ]; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 17e6fba8ac9a5..425ca28910073 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -99,125 +99,6 @@ pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> boo tcx.dep_graph.try_mark_green(tcx, dep_node).is_some() } -macro_rules! cycle_error_handling { - ([]) => {{ - rustc_middle::query::CycleErrorHandling::Error - }}; - ([(cycle_fatal) $($rest:tt)*]) => {{ - rustc_middle::query::CycleErrorHandling::Fatal - }}; - ([(cycle_stash) $($rest:tt)*]) => {{ - rustc_middle::query::CycleErrorHandling::Stash - }}; - ([(cycle_delay_bug) $($rest:tt)*]) => {{ - rustc_middle::query::CycleErrorHandling::DelayBug - }}; - ([$other:tt $($modifiers:tt)*]) => { - cycle_error_handling!([$($modifiers)*]) - }; -} - -macro_rules! is_anon { - ([]) => {{ - false - }}; - ([(anon) $($rest:tt)*]) => {{ - true - }}; - ([$other:tt $($modifiers:tt)*]) => { - is_anon!([$($modifiers)*]) - }; -} - -macro_rules! is_eval_always { - ([]) => {{ - false - }}; - ([(eval_always) $($rest:tt)*]) => {{ - true - }}; - ([$other:tt $($modifiers:tt)*]) => { - is_eval_always!([$($modifiers)*]) - }; -} - -macro_rules! is_depth_limit { - ([]) => {{ - false - }}; - ([(depth_limit) $($rest:tt)*]) => {{ - true - }}; - ([$other:tt $($modifiers:tt)*]) => { - is_depth_limit!([$($modifiers)*]) - }; -} - -macro_rules! is_feedable { - ([]) => {{ - false - }}; - ([(feedable) $($rest:tt)*]) => {{ - true - }}; - ([$other:tt $($modifiers:tt)*]) => { - is_feedable!([$($modifiers)*]) - }; -} - -/// Expands to `$yes` if the `no_hash` modifier is present, or `$no` otherwise. -macro_rules! if_no_hash { - ([] $yes:tt $no:tt) => { $no }; - ([(no_hash) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes }; - ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { - if_no_hash!([$($modifiers)*] $yes $no) - } -} - -macro_rules! call_provider { - ([][$tcx:expr, $name:ident, $key:expr]) => {{ - ($tcx.query_system.local_providers.$name)($tcx, $key) - }}; - ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{ - if let Some(key) = $key.as_local_key() { - ($tcx.query_system.local_providers.$name)($tcx, key) - } else { - ($tcx.query_system.extern_providers.$name)($tcx, $key) - } - }}; - ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { - call_provider!([$($modifiers)*][$($args)*]) - }; -} - -/// Expands to one of two token trees, depending on whether the current query -/// has the `cache_on_disk_if` modifier. -macro_rules! if_cache_on_disk { - ([] $yes:tt $no:tt) => { - $no - }; - // The `cache_on_disk_if` modifier generates a synthetic `(cache_on_disk)`, - // modifier, for use by this macro and similar macros. - ([(cache_on_disk) $($rest:tt)*] $yes:tt $no:tt) => { - $yes - }; - ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { - if_cache_on_disk!([$($modifiers)*] $yes $no) - }; -} - -/// Conditionally expands to some token trees, if the current query has the -/// `cache_on_disk_if` modifier. -macro_rules! item_if_cache_on_disk { - ([] $($item:tt)*) => {}; - ([(cache_on_disk) $($rest:tt)*] $($item:tt)*) => { - $($item)* - }; - ([$other:tt $($modifiers:tt)*] $($item:tt)*) => { - item_if_cache_on_disk! { [$($modifiers)*] $($item)* } - }; -} - /// The deferred part of a deferred query stack frame. fn mk_query_stack_frame_extra<'tcx, Cache>( (tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key), @@ -421,8 +302,20 @@ macro_rules! define_queries { queries { $( $(#[$attr:meta])* - [$($modifiers:tt)*] - fn $name:ident($K:ty) -> $V:ty, + fn $name:ident($K:ty) -> $V:ty + { + // Search for (QMODLIST) to find all occurrences of this query modifier list. + anon: $anon:literal, + arena_cache: $arena_cache:literal, + cache_on_disk: $cache_on_disk:literal, + cycle_error_handling: $cycle_error_handling:ident, + depth_limit: $depth_limit:literal, + eval_always: $eval_always:literal, + feedable: $feedable:literal, + no_hash: $no_hash:literal, + return_result_from_ensure_ok: $return_result_from_ensure_ok:literal, + separate_provide_extern: $separate_provide_extern:literal, + } )* } // Non-queries are unused here. @@ -498,7 +391,16 @@ macro_rules! define_queries { 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]); + + #[cfg($separate_provide_extern)] + let provided_value = if let Some(local_key) = key.as_local_key() { + (tcx.query_system.local_providers.$name)(tcx, local_key) + } else { + (tcx.query_system.extern_providers.$name)(tcx, key) + }; + + #[cfg(not($separate_provide_extern))] + let provided_value = (tcx.query_system.local_providers.$name)(tcx, key); rustc_middle::ty::print::with_reduced_queries!({ tracing::trace!(?provided_value); @@ -515,64 +417,67 @@ macro_rules! define_queries { { QueryVTable { name: stringify!($name), - anon: is_anon!([$($modifiers)*]), - eval_always: is_eval_always!([$($modifiers)*]), - depth_limit: is_depth_limit!([$($modifiers)*]), - feedable: is_feedable!([$($modifiers)*]), + anon: $anon, + eval_always: $eval_always, + depth_limit: $depth_limit, + feedable: $feedable, dep_kind: dep_graph::DepKind::$name, - cycle_error_handling: cycle_error_handling!([$($modifiers)*]), + cycle_error_handling: + rustc_middle::query::CycleErrorHandling::$cycle_error_handling, state: Default::default(), cache: Default::default(), - will_cache_on_disk_for_key_fn: if_cache_on_disk!([$($modifiers)*] { - Some(::rustc_middle::queries::_cache_on_disk_if_fns::$name) - } { - None - }), + + #[cfg($cache_on_disk)] + will_cache_on_disk_for_key_fn: + Some(rustc_middle::queries::_cache_on_disk_if_fns::$name), + #[cfg(not($cache_on_disk))] + will_cache_on_disk_for_key_fn: None, + call_query_method_fn: |tcx, key| { // Call the query method for its side-effect of loading a value // from disk-cache; the caller doesn't need the value. let _ = tcx.$name(key); }, invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace, - try_load_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { - Some(|tcx, key, prev_index, index| { - // Check the `cache_on_disk_if` condition for this key. - if !::rustc_middle::queries::_cache_on_disk_if_fns::$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 + + #[cfg($cache_on_disk)] + try_load_from_disk_fn: Some(|tcx, key, prev_index, index| { + // Check the `cache_on_disk_if` condition for this key. + if !rustc_middle::queries::_cache_on_disk_if_fns::$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)) }), - is_loadable_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { - Some(|tcx, key, index| -> bool { - ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && - $crate::plumbing::loadable_from_disk(tcx, index) - }) - } { - None + #[cfg(not($cache_on_disk))] + try_load_from_disk_fn: None, + + #[cfg($cache_on_disk)] + is_loadable_from_disk_fn: Some(|tcx, key, index| -> bool { + rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && + $crate::plumbing::loadable_from_disk(tcx, index) }), + #[cfg(not($cache_on_disk))] + is_loadable_from_disk_fn: None, + value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = FromCycleError::from_cycle_error(tcx, cycle, guar); erase::erase_val(result) }, - hash_value_fn: if_no_hash!( - [$($modifiers)*] - None - { - Some(|hcx, erased_value: &erase::Erased>| { - let value = erase::restore_val(*erased_value); - rustc_middle::dep_graph::hash_result(hcx, &value) - }) - } - ), + + #[cfg($no_hash)] + hash_value_fn: None, + #[cfg(not($no_hash))] + hash_value_fn: Some(|hcx, erased_value: &erase::Erased>| { + let value = erase::restore_val(*erased_value); + rustc_middle::dep_graph::hash_result(hcx, &value) + }), + format_value: |value| format!("{:?}", erase::restore_val::>(*value)), description_fn: $crate::queries::_description_fns::$name, execute_query_fn: if incremental { @@ -670,8 +575,8 @@ macro_rules! define_queries { query_result_index: &mut EncodedDepNodeIndex, ) { $( - item_if_cache_on_disk! { - [$($modifiers)*] + #[cfg($cache_on_disk)] + { $crate::plumbing::encode_query_results( tcx, &tcx.query_system.query_vtables.$name,