From b3bbeb4953e4d6bec4bc627cd58c01f8c9936f8f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 23 Feb 2026 10:46:39 +1100 Subject: [PATCH 1/4] Remove the `_description_fns` module. `rustc_queries` generates a macro and three modules. One of the modules looks like this: ``` mod _description_fns { ... #[allow(unused_variables)] pub fn hir_module_items<'tcx>(tcx: TyCtxt<'tcx>, key: LocalModDefId) -> String { format!("getting HIR module items in `{}`", tcx.def_path_str(key)) } ... } ``` Members of this module are then used to initialize `QueryVTables::description_fn` fields. This commit removes the `_description_fns` module entirely. For each query we now instead generate a description closure that is used to initialize `QueryVTables::description_fn`. This closure is passed as `(desc { $desc_fn_closure })` in the modifiers list. This makes the handling of the `desc` modifier closer to the handling of the other modifiers (though it's still a bit special). This change simplifies `rustc_queries` quite a bit, eliminating an entire module from its output, at the cost of complicating `define_queries` slightly. This is a good trade-off because the declarative macro is easier to understand than the proc macro. --- compiler/rustc_macros/src/query.rs | 33 +++++------------------ compiler/rustc_middle/src/queries.rs | 2 -- compiler/rustc_query_impl/src/lib.rs | 9 +++++-- compiler/rustc_query_impl/src/plumbing.rs | 15 ++++++++--- 4 files changed, 25 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index ebfcb50e9cde5..cc0c3030b3a12 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -280,7 +280,6 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result(tcx: TyCtxt<'tcx>, #key_pat: #key_ty) -> String { - format!(#expr_list) - } - }; - - streams.description_fns_stream.extend(quote! { - #desc - }); } /// Add hints for rust-analyzer @@ -413,7 +399,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { } for query in queries.0 { - let Query { doc_comments, name, key_ty, return_ty, modifiers, .. } = &query; + let Query { doc_comments, name, key_pat, key_ty, return_ty, modifiers, .. } = &query; // Normalize an absent return type into `-> ()` to make macro-rules parsing easier. let return_ty = match return_ty { @@ -431,6 +417,10 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { } } + // Put a description closure inside the `desc` modifier: `(desc { })`. + let expr_list = &modifiers.desc.expr_list; + modifiers_out.push(quote! { (desc { |tcx, #key_pat| format!(#expr_list) }) }); + passthrough!( arena_cache, cycle_fatal, @@ -485,7 +475,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { make_helpers_for_query(&query, &mut helpers); } - let HelperTokenStreams { description_fns_stream, cache_on_disk_if_fns_stream } = helpers; + let HelperTokenStreams { cache_on_disk_if_fns_stream } = helpers; TokenStream::from(quote! { /// Higher-order macro that invokes the specified macro with a prepared @@ -516,17 +506,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { #analyzer_stream } - /// Functions that format a human-readable description of each query - /// and its key, as specified by the `desc` query modifier. - /// - /// (The leading `_` avoids collisions with actual query names when - /// expanded in `rustc_middle::queries`, and makes this macro-generated - /// module easier to search for.) - pub mod _description_fns { - use super::*; - #description_fns_stream - } - // FIXME(Zalathar): Instead of declaring these functions directly, can // we put them in a macro and then expand that macro downstream in // `rustc_query_impl`, where the functions are actually used? diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index e303a8aeab917..eafb20eec4aae 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -120,7 +120,6 @@ use crate::mir::interpret::{ use crate::mir::mono::{ CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, }; -use crate::query::describe_as_module; use crate::query::plumbing::CyclePlaceholder; use crate::traits::query::{ CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, @@ -135,7 +134,6 @@ use crate::traits::{ }; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; -use crate::ty::print::PrintTraitRefExt; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ self, CrateInherentImpls, GenericArg, GenericArgsRef, LitToConstInput, PseudoCanonicalInput, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 890c0b2ef92c7..08403360e1629 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -9,12 +9,17 @@ // tidy-alphabetical-end use rustc_data_structures::sync::AtomicU64; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::dep_graph; use rustc_middle::queries::{self, ExternProviders, Providers}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; -use rustc_middle::query::{AsLocalKey, QueryCache, QueryMode}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::query::{ + AsLocalKey, QueryCache, QueryMode, describe_as_module, +}; +use rustc_middle::ty::print::PrintTraitRefExt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 7b5fd76c31958..41790a41980b7 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -268,6 +268,13 @@ macro_rules! item_if_cache_on_disk { }; } +/// Extract the description closure from the `desc` modifier, which must be present. +macro_rules! desc_fn { + ([] $($item:tt)*) => { compile_error!("query missing `desc`") }; + ([(desc { $desc_fn_closure:expr }) $($rest:tt)*]) => { $desc_fn_closure }; + ([$other:tt $($modifiers:tt)*]) => { desc_fn! { [$($modifiers)*] } }; +} + /// 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), @@ -597,12 +604,14 @@ macro_rules! define_queries { None }), value_from_cycle_error: |tcx, cycle, guar| { - let result: queries::$name::Value<'tcx> = 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, + format_value: |value| + format!("{:?}", erase::restore_val::>(*value)), + description_fn: desc_fn!([$($modifiers)*]), execute_query_fn: if incremental { query_impl::$name::get_query_incr::__rust_end_short_backtrace } else { From 33e27c7a136429b6a06b65b375867eb954dc2793 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 24 Feb 2026 19:06:13 +1100 Subject: [PATCH 2/4] Streamline cache-related query functions. There are three query vtable functions related to the `cache_on_disk_if` modifier: - `will_cache_on_disk_for_key_fn` - `try_load_from_disk_fn` - `is_loadable_from_disk_fn` These are all function ptrs within an `Option`. They each have a wrapper that returns `false`/`None` if the function ptr is missing. This commit removes the `Option` wrappers. In the `None` case we now set the function ptr to a trivial closure that returns `false`/`None`. The commit also removes some typedefs that each have a single use. All this is a bit simpler, with less indirection. More importantly, it enables the following commit, which will make more related changes. --- compiler/rustc_middle/src/query/plumbing.rs | 31 ++++++++------------- compiler/rustc_query_impl/src/plumbing.rs | 20 ++++++------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 9141f49bd45de..fe2999addb2c8 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -63,18 +63,6 @@ pub enum CycleErrorHandling { Stash, } -pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool; - -pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( - tcx: TyCtxt<'tcx>, - key: &Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, -) -> Option; - -pub type IsLoadableFromDiskFn<'tcx, Key> = - fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool; - pub type HashResult = Option, &V) -> Fingerprint>; #[derive(Clone, Debug)] @@ -129,7 +117,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub cycle_error_handling: CycleErrorHandling, pub state: QueryState<'tcx, C::Key>, pub cache: C, - pub will_cache_on_disk_for_key_fn: Option>, + pub will_cache_on_disk_for_key_fn: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, /// Function pointer that calls `tcx.$query(key)` for this query and /// discards the returned value. @@ -145,8 +133,14 @@ pub struct QueryVTable<'tcx, C: QueryCache> { /// This should be the only code that calls the provider function. pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, - pub try_load_from_disk_fn: Option>, - pub is_loadable_from_disk_fn: Option>, + pub try_load_from_disk_fn: fn( + tcx: TyCtxt<'tcx>, + key: &C::Key, + prev_index: SerializedDepNodeIndex, + index: DepNodeIndex, + ) -> Option, + pub is_loadable_from_disk_fn: + fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, pub hash_result: HashResult, pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value, @@ -176,7 +170,7 @@ impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> { impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { #[inline(always)] pub fn will_cache_on_disk_for_key(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool { - self.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key)) + (self.will_cache_on_disk_for_key_fn)(tcx, key) } #[inline(always)] @@ -187,8 +181,7 @@ impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option { - // `?` will return None immediately for queries that never cache to disk. - self.try_load_from_disk_fn?(tcx, key, prev_index, index) + (self.try_load_from_disk_fn)(tcx, key, prev_index, index) } #[inline] @@ -198,7 +191,7 @@ impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { key: &C::Key, index: SerializedDepNodeIndex, ) -> bool { - self.is_loadable_from_disk_fn.map_or(false, |f| f(tcx, key, index)) + (self.is_loadable_from_disk_fn)(tcx, key, index) } /// Synthesize an error value to let compilation continue after a cycle. diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 41790a41980b7..81d94b209c423 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -569,9 +569,9 @@ macro_rules! define_queries { 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) + rustc_middle::queries::_cache_on_disk_if_fns::$name } { - None + |_tcx, _key| false }), call_query_method_fn: |tcx, key| { // Call the query method for its side-effect of loading a value @@ -580,9 +580,9 @@ macro_rules! define_queries { }, 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| { + |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) { + if !::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, &key) { return None; } @@ -591,17 +591,17 @@ macro_rules! define_queries { // Arena-alloc the value if appropriate, and erase it. Some(queries::$name::provided_to_erased(tcx, value)) - }) + } } { - None + |_tcx, _key, _prev_index, _index| None }), 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) && + |tcx, key, index| -> bool { + ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, &key) && $crate::plumbing::loadable_from_disk(tcx, index) - }) + } } { - None + |_tcx, _key, _index| false }), value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = From 462ae3754bd167992946118c8d5837030119b2a1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 24 Feb 2026 19:06:33 +1100 Subject: [PATCH 3/4] Remove the `_cache_on_disk_if_fns` module. One of the modules generated by `rustc_queries` looks like this: ``` mod _cache_on_disk_if_fns { ... #[inline] pub fn const_param_default<'tcx>( _: TyCtxt<'tcx>, param: &crate::queries::const_param_default::Key<'tcx> ) -> bool { param.is_local() } ... ``` Members of this module are used to initialize multiple `QueryVTable` fields. This commit removes the `_cache_on_disk_if_fns` module entirely. For each cacheable query we generate a check closure which is passed as `(cache_on_disk_if { $check_closure }` in the modifiers list. This is similar to how `desc` modifiers are handled. --- Cargo.lock | 1 + compiler/rustc_macros/src/query.rs | 66 ++++++--------------- compiler/rustc_middle/src/queries.rs | 1 - compiler/rustc_middle/src/query/plumbing.rs | 2 + compiler/rustc_query_impl/Cargo.toml | 1 + compiler/rustc_query_impl/src/lib.rs | 9 ++- compiler/rustc_query_impl/src/plumbing.rs | 49 +++++++++------ 7 files changed, 58 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06d6928e1dfd5..d18276b030cb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4492,6 +4492,7 @@ version = "0.0.0" dependencies = [ "measureme", "rustc_abi", + "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_hir", diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index cc0c3030b3a12..e8f1cfcf0d30a 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -273,38 +273,6 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result(tcx: TyCtxt<'tcx>, #key_pat: &#key_ty) -> bool - #block - }); - } -} - /// Add hints for rust-analyzer fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::TokenStream) { // Add links to relevant modifiers @@ -384,7 +352,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { let queries = parse_macro_input!(input as List); let mut query_stream = quote! {}; - let mut helpers = HelperTokenStreams::default(); let mut analyzer_stream = quote! {}; let mut errors = quote! {}; @@ -435,11 +402,23 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { 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) }); + // If there was a `cache_on_disk_if` modifier, put a closure inside it: + // `(cache_on_disk { }`. + if let Some(CacheOnDiskIf { block, .. }) = &modifiers.cache_on_disk_if { + modifiers_out.push(quote! { + (cache_on_disk_if { + // `pass_by_value`: some keys are marked with `rustc_pass_by_value`, but we + // take keys by reference here. + // FIXME: `pass_by_value` is badly named; `allow(rustc::pass_by_value)` + // actually means "allow pass by reference of `rustc_pass_by_value` types". + // + // The type annotations are required to avoid compile errors, which is annoying + // because it necessitates extra `use` items in the file using + // `rustc_with_all_queries!`. + #[allow(rustc::pass_by_value)] + |tcx: TyCtxt<'_>, #key_pat: &#key_ty| #block + }) + }); } // This uses the span of the query definition for the commas, @@ -472,11 +451,8 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { } add_to_analyzer_stream(&query, &mut analyzer_stream); - make_helpers_for_query(&query, &mut helpers); } - let HelperTokenStreams { 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). @@ -506,14 +482,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { #analyzer_stream } - // FIXME(Zalathar): Instead of declaring these functions directly, can - // we put them in a macro and then expand that macro downstream in - // `rustc_query_impl`, where the functions are actually used? - pub mod _cache_on_disk_if_fns { - use super::*; - #cache_on_disk_if_fns_stream - } - #errors }) } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index eafb20eec4aae..ad6cd198c6567 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -96,7 +96,6 @@ use rustc_session::cstore::{ CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, }; use rustc_session::lint::LintExpectationId; -use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, LocalExpnId, Span, Symbol}; use rustc_target::spec::PanicStrategy; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index fe2999addb2c8..d8b6bae24d82e 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -139,8 +139,10 @@ pub struct QueryVTable<'tcx, C: QueryCache> { prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option, + pub is_loadable_from_disk_fn: fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, + pub hash_result: HashResult, pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value, diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 449d2ed5334a8..0b7efa0c20f89 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start measureme = "12.0.1" rustc_abi = { path = "../rustc_abi" } +rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 08403360e1629..ebdfa13a2a37a 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -5,13 +5,17 @@ #![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] #![feature(try_blocks)] // tidy-alphabetical-end +use rustc_ast::tokenstream::TokenStream; use rustc_data_structures::sync::AtomicU64; use rustc_hir::def::DefKind; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::dep_graph; +use rustc_middle::mir::interpret::GlobalId; +use rustc_middle::mir::mono::CollectionMode; use rustc_middle::queries::{self, ExternProviders, Providers}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; @@ -19,8 +23,9 @@ use rustc_middle::query::{ AsLocalKey, QueryCache, QueryMode, describe_as_module, }; use rustc_middle::ty::print::PrintTraitRefExt; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::Span; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt}; +use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId}; +use rustc_span::{LocalExpnId, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; pub use crate::job::{QueryJobMap, break_query_cycles, print_query_stack}; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 81d94b209c423..28b77a0a28720 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -242,29 +242,42 @@ macro_rules! call_provider { /// 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 { +macro_rules! if_cache_on_disk_if { ([] $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) => { + // Ignore the closure. + ([(cache_on_disk_if { $_:expr }) $($rest:tt)*] $yes:tt $no:tt) => { $yes }; ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { - if_cache_on_disk!([$($modifiers)*] $yes $no) + if_cache_on_disk_if!([$($modifiers)*] $yes $no) + }; +} + +/// Extract the closure from the `cache_on_disk_if` modifier if present, otherwise generate a +/// trivial failing closure. +macro_rules! cache_on_disk_if_fn { + ([] $($item:tt)*) => { + |_tcx, _key| false + }; + ([(cache_on_disk_if { $cache_closure:expr }) $($rest:tt)*]) => { + $cache_closure + }; + ([$other:tt $($modifiers:tt)*]) => { + cache_on_disk_if_fn! { [$($modifiers)*] } }; } /// Conditionally expands to some token trees, if the current query has the /// `cache_on_disk_if` modifier. -macro_rules! item_if_cache_on_disk { +macro_rules! item_if_cache_on_disk_if { ([] $($item:tt)*) => {}; - ([(cache_on_disk) $($rest:tt)*] $($item:tt)*) => { + ([(cache_on_disk_if { $_:expr }) $($rest:tt)*] $($item:tt)*) => { $($item)* }; ([$other:tt $($modifiers:tt)*] $($item:tt)*) => { - item_if_cache_on_disk! { [$($modifiers)*] $($item)* } + item_if_cache_on_disk_if! { [$($modifiers)*] $($item)* } }; } @@ -568,21 +581,18 @@ macro_rules! define_queries { cycle_error_handling: cycle_error_handling!([$($modifiers)*]), state: Default::default(), cache: Default::default(), - will_cache_on_disk_for_key_fn: if_cache_on_disk!([$($modifiers)*] { - rustc_middle::queries::_cache_on_disk_if_fns::$name - } { - |_tcx, _key| false - }), + will_cache_on_disk_for_key_fn: cache_on_disk_if_fn!([$($modifiers)*]), 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)*] { + try_load_from_disk_fn: if_cache_on_disk_if!([$($modifiers)*] { |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) { + let cache_on_disk_if_fn = cache_on_disk_if_fn!([$($modifiers)*]); + if !cache_on_disk_if_fn(tcx, key) { return None; } @@ -595,9 +605,10 @@ macro_rules! define_queries { } { |_tcx, _key, _prev_index, _index| None }), - is_loadable_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { + is_loadable_from_disk_fn: if_cache_on_disk_if!([$($modifiers)*] { |tcx, key, index| -> bool { - ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, &key) && + let cache_on_disk_if_fn = cache_on_disk_if_fn!([$($modifiers)*]); + cache_on_disk_if_fn(tcx, key) && $crate::plumbing::loadable_from_disk(tcx, index) } } { @@ -678,7 +689,7 @@ macro_rules! define_queries { ) } - item_if_cache_on_disk! { [$($modifiers)*] + item_if_cache_on_disk_if! { [$($modifiers)*] pub(crate) fn encode_query_results<'tcx>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, @@ -739,7 +750,7 @@ macro_rules! define_queries { > ] = &[ $( - if_cache_on_disk!([$($modifiers)*] { + if_cache_on_disk_if!([$($modifiers)*] { Some(query_impl::$name::encode_query_results) } { None From 9cc3fcd6a85aae14cbc98096544f15d6dd6d67dd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 25 Feb 2026 09:13:55 +1100 Subject: [PATCH 4/4] Remove trivial `QueryVTable` methods. These are now just trivial wrappers around the fn ptrs. Might as well just call the fn ptrs directly. --- compiler/rustc_macros/src/query.rs | 2 +- compiler/rustc_middle/src/query/plumbing.rs | 36 --------------------- compiler/rustc_query_impl/src/execution.rs | 16 +++++---- compiler/rustc_query_impl/src/lib.rs | 4 +-- compiler/rustc_query_impl/src/plumbing.rs | 4 +-- 5 files changed, 13 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index e8f1cfcf0d30a..f859473799cae 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -406,7 +406,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { // `(cache_on_disk { }`. if let Some(CacheOnDiskIf { block, .. }) = &modifiers.cache_on_disk_if { modifiers_out.push(quote! { - (cache_on_disk_if { + (cache_on_disk_if { // `pass_by_value`: some keys are marked with `rustc_pass_by_value`, but we // take keys by reference here. // FIXME: `pass_by_value` is badly named; `allow(rustc::pass_by_value)` diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index d8b6bae24d82e..a3fa6df0f662f 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -170,42 +170,6 @@ impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> { } impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { - #[inline(always)] - pub fn will_cache_on_disk_for_key(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool { - (self.will_cache_on_disk_for_key_fn)(tcx, key) - } - - #[inline(always)] - pub fn try_load_from_disk( - &self, - tcx: TyCtxt<'tcx>, - key: &C::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option { - (self.try_load_from_disk_fn)(tcx, key, prev_index, index) - } - - #[inline] - pub fn is_loadable_from_disk( - &self, - tcx: TyCtxt<'tcx>, - key: &C::Key, - index: SerializedDepNodeIndex, - ) -> bool { - (self.is_loadable_from_disk_fn)(tcx, key, index) - } - - /// Synthesize an error value to let compilation continue after a cycle. - pub fn value_from_cycle_error( - &self, - tcx: TyCtxt<'tcx>, - cycle_error: &CycleError, - guar: ErrorGuaranteed, - ) -> C::Value { - (self.value_from_cycle_error)(tcx, cycle_error, guar) - } - pub fn construct_dep_node(&self, tcx: TyCtxt<'tcx>, key: &C::Key) -> DepNode { DepNode::construct(tcx, self.dep_kind, key) } diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 655dbe52df3e6..cd52fca9a97e6 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -120,7 +120,7 @@ fn handle_cycle_error<'tcx, C: QueryCache>( match query.cycle_error_handling { CycleErrorHandling::Error => { let guar = error.emit(); - query.value_from_cycle_error(tcx, cycle_error, guar) + (query.value_from_cycle_error)(tcx, cycle_error, guar) } CycleErrorHandling::Fatal => { error.emit(); @@ -129,7 +129,7 @@ fn handle_cycle_error<'tcx, C: QueryCache>( } CycleErrorHandling::DelayBug => { let guar = error.delay_as_bug(); - query.value_from_cycle_error(tcx, cycle_error, guar) + (query.value_from_cycle_error)(tcx, cycle_error, guar) } CycleErrorHandling::Stash => { let guar = if let Some(root) = cycle_error.cycle.first() @@ -139,7 +139,7 @@ fn handle_cycle_error<'tcx, C: QueryCache>( } else { error.emit() }; - query.value_from_cycle_error(tcx, cycle_error, guar) + (query.value_from_cycle_error)(tcx, cycle_error, guar) } } } @@ -506,7 +506,9 @@ fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache>( // First we try to load the result from the on-disk cache. // Some things are never cached on disk. - if let Some(result) = query.try_load_from_disk(tcx, key, prev_dep_node_index, dep_node_index) { + if let Some(result) = + (query.try_load_from_disk_fn)(tcx, key, prev_dep_node_index, dep_node_index) + { if std::intrinsics::unlikely(tcx.sess.opts.unstable_opts.query_dep_graph) { dep_graph_data.mark_debug_loaded_from_disk(*dep_node) } @@ -539,7 +541,7 @@ fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache>( // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !query.will_cache_on_disk_for_key(tcx, key) + !(query.will_cache_on_disk_for_key_fn)(tcx, key) || !tcx.key_fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {dep_node:?}" ); @@ -547,7 +549,7 @@ fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache>( // Sanity check for the logic in `ensure`: if the node is green and the result loadable, // we should actually be able to load it. debug_assert!( - !query.is_loadable_from_disk(tcx, key, prev_dep_node_index), + !(query.is_loadable_from_disk_fn)(tcx, key, prev_dep_node_index), "missing on-disk cache entry for loadable {dep_node:?}" ); @@ -644,7 +646,7 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>( // In ensure-done mode, we can only skip execution for this key if // there's a disk-cached value available to load later if needed, // which guarantees the query provider will never run for this key. - let is_loadable = query.is_loadable_from_disk(tcx, key, serialized_dep_node_index); + let is_loadable = (query.is_loadable_from_disk_fn)(tcx, key, serialized_dep_node_index); EnsureCanSkip { skip_execution: is_loadable, dep_node: Some(dep_node) } } } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index ebdfa13a2a37a..55e59b58b7817 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -19,9 +19,7 @@ use rustc_middle::mir::mono::CollectionMode; use rustc_middle::queries::{self, ExternProviders, Providers}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; -use rustc_middle::query::{ - AsLocalKey, QueryCache, QueryMode, describe_as_module, -}; +use rustc_middle::query::{AsLocalKey, QueryCache, QueryMode, describe_as_module}; use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId}; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 28b77a0a28720..c5c0ca4cf24ed 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -358,7 +358,7 @@ pub(crate) fn encode_query_results_inner<'a, 'tcx, C, V>( assert!(all_inactive(&query.state)); query.cache.iter(&mut |key, value, dep_node| { - if query.will_cache_on_disk_for_key(tcx, key) { + if (query.will_cache_on_disk_for_key_fn)(tcx, key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. @@ -411,7 +411,7 @@ pub(crate) fn try_load_from_on_disk_cache_inner<'tcx, C: QueryCache>( dep_node.key_fingerprint ) }); - if query.will_cache_on_disk_for_key(tcx, &key) { + if (query.will_cache_on_disk_for_key_fn)(tcx, &key) { // Call `tcx.$query(key)` for its side-effect of loading the disk-cached // value into memory. (query.call_query_method_fn)(tcx, key);