From d9b7a6774e492203ea9f1163b79372a889544dcc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 6 Mar 2026 20:44:43 +1100 Subject: [PATCH 1/2] Remove cache-on-disk from query `check_liveness` This is the only query with a cache-on-disk condition other than `true` or is-local. Removing its cache-on-disk modifier entirely appears to not cause any serious perf regressions. --- compiler/rustc_middle/src/queries.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index db98d6cf5ae5b..41dc6df16d30c 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1218,7 +1218,6 @@ rustc_queries! { query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet { arena_cache desc { "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) } - cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) } } /// Return the live symbols in the crate for dead code check. From fa1b1fb9b58713722aa292253efbfdd19f6f7e37 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 6 Mar 2026 21:02:58 +1100 Subject: [PATCH 2/2] Simplify the `cache_on_disk_if` query modifier to just `cache_on_disk` This removes the explicit cache-on-disk condition. The default cache-on-disk condition is `true`. For queries that also have the `separate_provide_extern` modifier, values are only cached to disk if their key corresponds to the local provider, i.e. it corresponds to something in the local crate and not an extern crate. --- compiler/rustc_macros/src/query.rs | 56 ++------- compiler/rustc_middle/src/queries.rs | 120 +++++++++---------- compiler/rustc_middle/src/query/modifiers.rs | 17 ++- compiler/rustc_middle/src/query/plumbing.rs | 2 +- compiler/rustc_query_impl/src/execution.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 27 +++-- 6 files changed, 105 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 8f0bfed2035c8..dc1e391c3fe28 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -5,8 +5,8 @@ use syn::parse::{Parse, ParseStream, Result}; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{ - AttrStyle, Attribute, Block, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced, - parenthesized, parse_macro_input, token, + AttrStyle, Attribute, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced, parenthesized, + parse_macro_input, token, }; mod kw { @@ -132,17 +132,12 @@ struct Desc { expr_list: Punctuated, } -struct CacheOnDiskIf { - modifier: Ident, - block: Block, -} - /// See `rustc_middle::query::modifiers` for documentation of each query modifier. struct QueryModifiers { // tidy-alphabetical-start anon: Option, arena_cache: Option, - cache_on_disk_if: Option, + cache_on_disk: Option, cycle_delay_bug: Option, cycle_stash: Option, depth_limit: Option, @@ -157,7 +152,7 @@ struct QueryModifiers { fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut arena_cache = None; - let mut cache_on_disk_if = None; + let mut cache_on_disk = None; let mut desc = None; let mut cycle_delay_bug = None; let mut cycle_stash = None; @@ -188,11 +183,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { braced!(attr_content in input); let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?; try_insert!(desc = Desc { modifier, expr_list }); - } else if modifier == "cache_on_disk_if" { - // Parse a cache-on-disk modifier like: - // `cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) }` - let block = input.parse()?; - try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block }); + } else if modifier == "cache_on_disk" { + try_insert!(cache_on_disk = modifier); } else if modifier == "arena_cache" { try_insert!(arena_cache = modifier); } else if modifier == "cycle_delay_bug" { @@ -222,7 +214,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { }; Ok(QueryModifiers { arena_cache, - cache_on_disk_if, + cache_on_disk, desc, cycle_delay_bug, cycle_stash, @@ -241,7 +233,7 @@ fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macr // tidy-alphabetical-start anon, arena_cache, - cache_on_disk_if, + cache_on_disk, cycle_delay_bug, cycle_stash, depth_limit, @@ -256,7 +248,7 @@ fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macr let anon = anon.is_some(); let arena_cache = arena_cache.is_some(); - let cache_on_disk = cache_on_disk_if.is_some(); + let cache_on_disk = cache_on_disk.is_some(); let cycle_error_handling = if cycle_delay_bug.is_some() { quote! { DelayBug } @@ -330,7 +322,6 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result(tcx: TyCtxt<'tcx>, #key_pat: &#key_ty) -> bool - #block - }); - } - let Desc { expr_list, .. } = &modifiers.desc; let desc = quote! { @@ -379,12 +358,6 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke crate::query::modifiers::#name; }); - if let Some(CacheOnDiskIf { modifier, .. }) = &modifiers.cache_on_disk_if { - modifiers_stream.extend(quote! { - crate::query::modifiers::#modifier; - }); - } - macro_rules! doc_link { ( $( $modifier:ident ),+ $(,)? ) => { $( @@ -399,6 +372,7 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke doc_link!( arena_cache, + cache_on_disk, cycle_delay_bug, cycle_stash, no_hash, @@ -506,7 +480,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 { description_fns_stream } = helpers; TokenStream::from(quote! { /// Higher-order macro that invokes the specified macro with (a) a list of all query @@ -542,14 +516,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { #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? - 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 41dc6df16d30c..61239692f2fa8 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -30,8 +30,6 @@ //! optional arguments. The query key identifier is available for use within the block, as is //! `tcx`. //! - `arena_cache`: Use an arena for in-memory caching of the query result. -//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to -//! true. The query key identifier is available for use within the block, as is `tcx`. //! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. //! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. //! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. @@ -162,7 +160,7 @@ rustc_queries! { /// The output is the token stream generated by the proc macro. query derive_macro_expansion(key: (LocalExpnId, &'tcx TokenStream)) -> Result<&'tcx TokenStream, ()> { desc { "expanding a derive (proc) macro" } - cache_on_disk_if { true } + cache_on_disk } /// This exists purely for testing the interactions between delayed bugs and incremental. @@ -243,7 +241,7 @@ rustc_queries! { query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { arena_cache desc { "getting HIR module items in `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } + cache_on_disk } /// Returns HIR ID for the given `LocalDefId`. @@ -291,7 +289,7 @@ rustc_queries! { /// E.g., given `struct Ty;` this returns `3` for `N`. query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { desc { "computing the default for const parameter `{}`", tcx.def_path_str(param) } - cache_on_disk_if { param.is_local() } + cache_on_disk separate_provide_extern } @@ -304,7 +302,7 @@ rustc_queries! { /// This query will ICE if given a const that is not marked with `type const`. query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { desc { "computing the type-level value for `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern } @@ -336,7 +334,7 @@ rustc_queries! { }, path = tcx.def_path_str(key), } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -390,7 +388,7 @@ rustc_queries! { -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -441,7 +439,7 @@ rustc_queries! { query generics_of(key: DefId) -> &'tcx ty::Generics { desc { "computing generics of `{}`", tcx.def_path_str(key) } arena_cache - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -455,7 +453,7 @@ rustc_queries! { /// the result of this query for use in UI tests or for debugging purposes. query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { "computing predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk } query opaque_types_defined_by( @@ -498,7 +496,7 @@ rustc_queries! { /// ``` query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { "finding item bounds for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -511,7 +509,7 @@ rustc_queries! { /// [explicit item bounds]: Self::explicit_item_bounds query explicit_item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { "finding item bounds for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -642,7 +640,7 @@ rustc_queries! { /// the final value of a `const`. query mir_const_qualif(key: DefId) -> mir::ConstQualifs { desc { "const checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -675,7 +673,7 @@ rustc_queries! { key: DefId ) -> &'tcx mir::Body<'tcx> { desc { "caching mir of `{}` for CTFE", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -710,7 +708,7 @@ rustc_queries! { query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> { arena_cache desc { "coroutine witness types for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -739,7 +737,7 @@ rustc_queries! { /// for codegen. This is also the only query that can fetch non-local MIR, at present. query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { desc { "optimizing MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -777,7 +775,7 @@ rustc_queries! { /// need to use the `DefId` of the original body. query promoted_mir(key: DefId) -> &'tcx IndexVec> { desc { "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -832,7 +830,7 @@ rustc_queries! { /// predicates with explicit spans for diagnostics purposes. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { "computing explicit predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -845,7 +843,7 @@ rustc_queries! { /// print the result of this query for use in UI tests or for debugging purposes. query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { desc { "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -859,7 +857,7 @@ rustc_queries! { /// predicates are available (note that super-predicates must not be cyclic). query explicit_super_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { "computing the super predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -871,7 +869,7 @@ rustc_queries! { /// predicates of the trait alias. query explicit_implied_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { "computing the implied predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -930,22 +928,22 @@ rustc_queries! { query trait_def(key: DefId) -> &'tcx ty::TraitDef { desc { "computing trait definition for `{}`", tcx.def_path_str(key) } arena_cache - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } query adt_def(key: DefId) -> ty::AdtDef<'tcx> { desc { "computing ADT definition for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } query adt_destructor(key: DefId) -> Option { desc { "computing `Drop` impl for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } query adt_async_destructor(key: DefId) -> Option { desc { "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } query adt_sizedness_constraint( @@ -1053,7 +1051,7 @@ rustc_queries! { /// the result of this query for use in UI tests or for debugging purposes. query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { desc { "computing the variances of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern cycle_delay_bug } @@ -1074,14 +1072,14 @@ rustc_queries! { /// to a list of the `DefId`s of its associated items or fields. query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { desc { "collecting associated items or fields of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } /// Maps from a trait/impl item to the trait/impl item "descriptor". query associated_item(key: DefId) -> ty::AssocItem { desc { "computing associated item data for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -1129,7 +1127,7 @@ rustc_queries! { /// Given an `impl_id`, return the trait it implements along with some header information. query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { desc { "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } - cache_on_disk_if { impl_id.is_local() } + cache_on_disk separate_provide_extern } @@ -1145,7 +1143,7 @@ rustc_queries! { /// Methods in these implementations don't need to be exported. query inherent_impls(key: DefId) -> &'tcx [DefId] { desc { "collecting inherent impls for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -1187,7 +1185,7 @@ rustc_queries! { /// Computes the signature of the function. query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { desc { "computing function signature of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern cycle_delay_bug } @@ -1243,19 +1241,19 @@ rustc_queries! { /// Caches `CoerceUnsized` kinds for impls on custom types. query coerce_unsized_info(key: DefId) -> Result { desc { "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern return_result_from_ensure_ok } query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { desc { "type-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { !tcx.is_typeck_child(key.to_def_id()) } + cache_on_disk } query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { desc { "finding used_trait_imports `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } + cache_on_disk } query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { @@ -1325,7 +1323,7 @@ rustc_queries! { "computing (transitive) callees of `{}` that may recurse", tcx.def_path_str(key), } - cache_on_disk_if { true } + cache_on_disk } /// Obtain all the calls into other local functions @@ -1363,7 +1361,7 @@ rustc_queries! { "const-evaluating + checking `{}`", key.value.display(tcx) } - cache_on_disk_if { true } + cache_on_disk } /// Evaluate a static's initializer, returning the allocation of the initializer's memory. @@ -1372,7 +1370,7 @@ rustc_queries! { "evaluating initializer of static `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -1396,7 +1394,7 @@ rustc_queries! { key.value.display(tcx) } depth_limit - cache_on_disk_if { true } + cache_on_disk } /// Evaluate a constant and convert it to a type level constant or @@ -1439,7 +1437,7 @@ rustc_queries! { query reachable_set(_: ()) -> &'tcx LocalDefIdSet { arena_cache desc { "reachability" } - cache_on_disk_if { true } + cache_on_disk } /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body; @@ -1463,12 +1461,12 @@ rustc_queries! { /// look up the correct symbol name of instances from upstream crates. query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName<'tcx> { desc { "computing the symbol for `{}`", key } - cache_on_disk_if { true } + cache_on_disk } query def_kind(def_id: DefId) -> DefKind { desc { "looking up definition kind of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -1476,7 +1474,7 @@ rustc_queries! { /// Gets the span for the definition. query def_span(def_id: DefId) -> Span { desc { "looking up span for `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -1484,7 +1482,7 @@ rustc_queries! { /// Gets the span for the identifier of the definition. query def_ident_span(def_id: DefId) -> Option { desc { "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -1493,18 +1491,18 @@ rustc_queries! { /// Panics if it is not a definition that has a single type. query ty_span(def_id: LocalDefId) -> Span { desc { "looking up span for `{}`'s type", tcx.def_path_str(def_id) } - cache_on_disk_if { true } + cache_on_disk } query lookup_stability(def_id: DefId) -> Option { desc { "looking up stability of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern } query lookup_const_stability(def_id: DefId) -> Option { desc { "looking up const stability of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern } @@ -1523,7 +1521,7 @@ rustc_queries! { query lookup_deprecation_entry(def_id: DefId) -> Option { desc { "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern } @@ -1558,7 +1556,7 @@ rustc_queries! { query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs { desc { "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } arena_cache - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern feedable } @@ -1593,7 +1591,7 @@ rustc_queries! { query is_mir_available(key: DefId) -> bool { desc { "checking if item has MIR available: `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } + cache_on_disk separate_provide_extern } @@ -1627,7 +1625,7 @@ rustc_queries! { query codegen_select_candidate( key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { - cache_on_disk_if { true } + cache_on_disk desc { "computing candidate for `{}`", key.value } } @@ -1649,7 +1647,7 @@ rustc_queries! { query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { desc { "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } - cache_on_disk_if { true } + cache_on_disk return_result_from_ensure_ok } query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { @@ -1738,7 +1736,7 @@ rustc_queries! { /// then `Err(AlwaysRequiresDrop)` is returned. query adt_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { desc { "computing when `{}` needs drop", tcx.def_path_str(def_id) } - cache_on_disk_if { true } + cache_on_disk } /// A list of types where the ADT requires async drop if and only if any of @@ -1746,7 +1744,7 @@ rustc_queries! { /// then `Err(AlwaysRequiresDrop)` is returned. query adt_async_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { desc { "computing when `{}` needs async drop", tcx.def_path_str(def_id) } - cache_on_disk_if { true } + cache_on_disk } /// A list of types where the ADT requires drop if and only if any of those types @@ -1875,7 +1873,7 @@ rustc_queries! { } query has_ffi_unwind_calls(key: LocalDefId) -> bool { desc { "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) } - cache_on_disk_if { true } + cache_on_disk } query required_panic_strategy(_: CrateNum) -> Option { desc { "getting a crate's required panic strategy" } @@ -1957,7 +1955,7 @@ rustc_queries! { } query is_reachable_non_generic(def_id: DefId) -> bool { desc { "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern } query is_unreachable_local_definition(def_id: LocalDefId) -> bool { @@ -2404,7 +2402,7 @@ rustc_queries! { /// sets of different crates do not intersect. query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { desc { "collecting exported non-generic symbols for crate `{}`", cnum} - cache_on_disk_if { *cnum == LOCAL_CRATE } + cache_on_disk separate_provide_extern } @@ -2417,7 +2415,7 @@ rustc_queries! { /// sets of different crates do not intersect. query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { desc { "collecting exported generic symbols for crate `{}`", cnum} - cache_on_disk_if { *cnum == LOCAL_CRATE } + cache_on_disk separate_provide_extern } @@ -2748,12 +2746,12 @@ rustc_queries! { query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>]), NormalizationErrorInMono> { desc { "collecting items used by `{}`", key.0 } - cache_on_disk_if { true } + cache_on_disk } query size_estimate(key: ty::Instance<'tcx>) -> usize { desc { "estimating codegen size of `{}`", key } - cache_on_disk_if { true } + cache_on_disk } query anon_const_kind(def_id: DefId) -> ty::AnonConstKind { @@ -2763,7 +2761,7 @@ rustc_queries! { query trivial_const(def_id: DefId) -> Option<(mir::ConstValue, Ty<'tcx>)> { desc { "checking if `{}` is a trivial const", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } + cache_on_disk separate_provide_extern } @@ -2785,7 +2783,7 @@ rustc_queries! { query externally_implementable_items(cnum: CrateNum) -> &'tcx FxIndexMap)> { arena_cache desc { "looking up the externally implementable items of a crate" } - cache_on_disk_if { *cnum == LOCAL_CRATE } + cache_on_disk separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs index c305f65a9ef35..1685223df5dee 100644 --- a/compiler/rustc_middle/src/query/modifiers.rs +++ b/compiler/rustc_middle/src/query/modifiers.rs @@ -18,10 +18,17 @@ pub(crate) struct anon; /// Use this type for the in-memory cache. pub(crate) struct arena_cache; -/// # `cache_on_disk_if` query modifier +/// # `cache_on_disk` query modifier /// -/// Cache the query to disk if the `Block` returns true. -pub(crate) struct cache_on_disk_if; +/// Cache the query's return values to disk, allowing them to be loaded in +/// future incremental-compilation sessions if their dep-graph dependencies are +/// all green. +/// +/// If the [`separate_provide_extern`] modifier is also present, values will +/// only be cached to disk if their key belongs to the local crate. Values +/// corresponding to extern-crate keys can typically be loaded from their +/// crate metadata instead. +pub(crate) struct cache_on_disk; /// # `cycle_delay_bug` query modifier /// @@ -74,7 +81,9 @@ pub(crate) struct return_result_from_ensure_ok; /// # `separate_provide_extern` query modifier /// -/// Use a separate query provider for local and extern crates +/// Use a separate query provider function for local and extern crates. +/// +/// Also affects the [`cache_on_disk`] modifier, if present. pub(crate) struct separate_provide_extern; // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index e1e69a9d0b262..d14b20655c7a4 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -128,7 +128,7 @@ 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 will_cache_on_disk_for_key_fn: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, + pub will_cache_on_disk_for_key_fn: fn(key: &C::Key) -> bool, pub try_load_from_disk_fn: fn( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 27b6214ed2887..7cef5deba2166 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -553,7 +553,7 @@ fn load_from_disk_or_invoke_provider_green<'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_fn)(tcx, key) + !(query.will_cache_on_disk_for_key_fn)(key) || !tcx.key_fingerprint_style(dep_node.kind).is_maybe_recoverable(), "missing on-disk cache entry for {dep_node:?}" ); diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 60c816a438365..1ded5daf79934 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -168,7 +168,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, C, V>( assert!(all_inactive(&query.state)); query.cache.for_each(&mut |key, value, dep_node| { - if (query.will_cache_on_disk_for_key_fn)(tcx, key) { + if (query.will_cache_on_disk_for_key_fn)(key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. @@ -221,7 +221,7 @@ pub(crate) fn promote_from_disk_inner<'tcx, Q: GetQueryVTable<'tcx>>( dep_node.key_fingerprint ) }); - if (query.will_cache_on_disk_for_key_fn)(tcx, &key) { + if (query.will_cache_on_disk_for_key_fn)(&key) { // Call `tcx.$query(key)` for its side-effect of loading the disk-cached // value into memory. (query.call_query_method_fn)(tcx, key); @@ -412,6 +412,20 @@ macro_rules! define_queries { } } + #[cfg($cache_on_disk)] + pub(crate) fn will_cache_on_disk_for_key<'tcx>( + _key: &queries::$name::Key<'tcx>, + ) -> bool { + // Don't use the disk cache for values that would be obtained + // from a separate extern provider, because they can probably be + // reloaded cheaply from the other crate's metadata instead. + #[cfg($separate_provide_extern)] + if rustc_middle::query::AsLocalQueryKey::as_local_key(_key).is_none() { + return false; + } + true + } + pub(crate) fn make_query_vtable<'tcx>(incremental: bool) -> QueryVTable<'tcx, queries::$name::Cache<'tcx>> { @@ -435,15 +449,14 @@ macro_rules! define_queries { invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace, #[cfg($cache_on_disk)] - will_cache_on_disk_for_key_fn: - rustc_middle::queries::_cache_on_disk_if_fns::$name, + will_cache_on_disk_for_key_fn: query_impl::$name::will_cache_on_disk_for_key, #[cfg(not($cache_on_disk))] - will_cache_on_disk_for_key_fn: |_, _| false, + will_cache_on_disk_for_key_fn: |_key| false, #[cfg($cache_on_disk)] try_load_from_disk_fn: |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 !query_impl::$name::will_cache_on_disk_for_key(key) { return None; } @@ -458,7 +471,7 @@ macro_rules! define_queries { #[cfg($cache_on_disk)] is_loadable_from_disk_fn: |tcx, key, index| -> bool { - rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && + query_impl::$name::will_cache_on_disk_for_key(key) && $crate::plumbing::loadable_from_disk(tcx, index) }, #[cfg(not($cache_on_disk))]