From de15ab0065f512908225603bd429cafe0054b424 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 22 Mar 2026 18:37:59 +1100 Subject: [PATCH 1/4] Store value/side-effect index lists inside `CacheEncoder` These lists can be considered part of the encoder state, and bundling them inside the encoder is certainly more convenient than passing them around separately. --- Cargo.lock | 1 - .../rustc_middle/src/dep_graph/serialized.rs | 9 ++ compiler/rustc_middle/src/hooks/mod.rs | 8 +- .../rustc_middle/src/query/on_disk_cache.rs | 89 ++++++++++--------- compiler/rustc_query_impl/Cargo.toml | 1 - compiler/rustc_query_impl/src/plumbing.rs | 26 ++---- 6 files changed, 64 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f2b417b24309..85997e1886f1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4573,7 +4573,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", - "rustc_index", "rustc_macros", "rustc_middle", "rustc_serialize", diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index e84d117db2aee..ef5e3d9268ad7 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -72,6 +72,15 @@ rustc_index::newtype_index! { pub struct SerializedDepNodeIndex {} } +impl SerializedDepNodeIndex { + /// Converts a current-session dep node index to a "serialized" index, + /// for the purpose of serializing data to be loaded by future sessions. + #[inline(always)] + pub fn from_curr_for_serialization(index: DepNodeIndex) -> Self { + SerializedDepNodeIndex::from_u32(index.as_u32()) + } +} + const DEP_NODE_SIZE: usize = size_of::(); /// Amount of padding we need to add to the edge list data so that we can retrieve every /// SerializedDepNodeIndex with a fixed-size read then mask. diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index 691096f4e47c2..c70ceef1d47e9 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -9,7 +9,7 @@ use rustc_span::def_id::{CrateNum, LocalDefId}; use rustc_span::{ExpnHash, ExpnId}; use crate::mir; -use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex}; +use crate::query::on_disk_cache::CacheEncoder; use crate::ty::{Ty, TyCtxt}; macro_rules! declare_hooks { @@ -111,10 +111,8 @@ declare_hooks! { /// Creates the MIR for a given `DefId`, including unreachable code. hook build_mir_inner_impl(def: LocalDefId) -> mir::Body<'tcx>; - hook encode_query_values( - encoder: &mut CacheEncoder<'_, 'tcx>, - query_result_index: &mut EncodedDepNodeIndex - ) -> (); + /// Serializes all eligible query return values into the on-disk cache. + hook encode_query_values(encoder: &mut CacheEncoder<'_, 'tcx>) -> (); } #[cold] diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 607891d4d19d9..b6409c1ea171e 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -9,7 +9,7 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId}; use rustc_hir::definitions::DefPathHash; -use rustc_index::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -62,13 +62,13 @@ pub struct OnDiskCache { // Caches that are populated lazily during decoding. file_index_to_file: Lock>>, - // A map from dep-node to the position of the cached query result in - // `serialized_data`. - query_result_index: FxHashMap, + /// For query dep nodes that have a disk-cached return value, maps the node + /// index to the position of its serialized value in `serialized_data`. + query_values_index: FxHashMap, - // A map from dep-node to the position of any associated `QuerySideEffect` in - // `serialized_data`. - prev_side_effects_index: FxHashMap, + /// For `DepKind::SideEffect` dep nodes, maps the node index to the position + /// of its serialized [`QuerySideEffect`] in `serialized_data`. + side_effects_index: FxHashMap, alloc_decoding_state: AllocDecodingState, @@ -101,8 +101,8 @@ pub struct OnDiskCache { #[derive(Encodable, Decodable)] struct Footer { file_index_to_stable_id: FxHashMap, - query_result_index: EncodedDepNodeIndex, - side_effects_index: EncodedDepNodeIndex, + query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, + side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, // The location of all allocations. // Most uses only need values up to u32::MAX, but benchmarking indicates that we can use a u64 // without measurable overhead. This permits larger const allocations without ICEing. @@ -114,8 +114,6 @@ struct Footer { foreign_expn_data: UnhashMap, } -pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; - #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)] struct SourceFileIndex(u32); @@ -175,8 +173,8 @@ impl OnDiskCache { file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), current_side_effects: Default::default(), - query_result_index: footer.query_result_index.into_iter().collect(), - prev_side_effects_index: footer.side_effects_index.into_iter().collect(), + query_values_index: footer.query_values_index.into_iter().collect(), + side_effects_index: footer.side_effects_index.into_iter().collect(), alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index), syntax_contexts: footer.syntax_contexts, expn_data: footer.expn_data, @@ -191,8 +189,8 @@ impl OnDiskCache { file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), current_side_effects: Default::default(), - query_result_index: Default::default(), - prev_side_effects_index: Default::default(), + query_values_index: Default::default(), + side_effects_index: Default::default(), alloc_decoding_state: AllocDecodingState::new(Vec::new()), syntax_contexts: FxHashMap::default(), expn_data: UnhashMap::default(), @@ -241,30 +239,19 @@ impl OnDiskCache { file_to_file_index, hygiene_context: &hygiene_encode_context, symbol_index_table: Default::default(), + query_values_index: Default::default(), + side_effects_index: Default::default(), }; - // Encode query results. - let mut query_result_index = EncodedDepNodeIndex::new(); - + // Encode query return values. tcx.sess.time("encode_query_values", || { - let enc = &mut encoder; - let qri = &mut query_result_index; - tcx.encode_query_values(enc, qri); + tcx.encode_query_values(&mut encoder); }); // Encode side effects. - let side_effects_index: EncodedDepNodeIndex = self - .current_side_effects - .borrow() - .iter() - .map(|(dep_node_index, side_effect)| { - let pos = AbsoluteBytePos::new(encoder.position()); - let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); - encoder.encode_tagged(dep_node_index, side_effect); - - (dep_node_index, pos) - }) - .collect(); + for (&dep_node_index, side_effect) in self.current_side_effects.borrow().iter() { + encoder.encode_side_effect(dep_node_index, side_effect); + } let interpret_alloc_index = { let mut interpret_alloc_index = Vec::new(); @@ -315,11 +302,13 @@ impl OnDiskCache { // Encode the file footer. let footer_pos = encoder.position() as u64; + let query_values_index = mem::take(&mut encoder.query_values_index); + let side_effects_index = mem::take(&mut encoder.side_effects_index); encoder.encode_tagged( TAG_FILE_FOOTER, &Footer { file_index_to_stable_id, - query_result_index, + query_values_index, side_effects_index, interpret_alloc_index, syntax_contexts, @@ -346,7 +335,7 @@ impl OnDiskCache { dep_node_index: SerializedDepNodeIndex, ) -> Option { let side_effect: Option = - self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index); + self.load_indexed(tcx, dep_node_index, &self.side_effects_index); side_effect } @@ -359,16 +348,15 @@ impl OnDiskCache { debug_assert!(prev.is_none()); } - /// Return whether the cached query result can be decoded. + /// Returns true if there is a disk-cached query return value for the given node. #[inline] pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool { - self.query_result_index.contains_key(&dep_node_index) + self.query_values_index.contains_key(&dep_node_index) // with_decoder is infallible, so we can stop here } - /// Returns the cached query result if there is something in the cache for - /// the given `SerializedDepNodeIndex`; otherwise returns `None`. - pub fn try_load_query_result<'tcx, T>( + /// Returns the disk-cached query return value for the given node, if there is one. + pub fn try_load_query_value<'tcx, T>( &self, tcx: TyCtxt<'tcx>, dep_node_index: SerializedDepNodeIndex, @@ -376,7 +364,7 @@ impl OnDiskCache { where T: for<'a> Decodable>, { - let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_result_index); + let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_values_index); debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index)); opt_value } @@ -815,6 +803,9 @@ pub struct CacheEncoder<'a, 'tcx> { hygiene_context: &'a HygieneEncodeContext, // Used for both `Symbol`s and `ByteSymbol`s. symbol_index_table: FxHashMap, + + query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, + side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, } impl<'a, 'tcx> fmt::Debug for CacheEncoder<'a, 'tcx> { @@ -835,7 +826,7 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> { /// encode the specified tag, then the given value, then the number of /// bytes taken up by tag and value. On decoding, we can then verify that /// we get the expected tag and read the expected number of bytes. - pub fn encode_tagged, V: Encodable>(&mut self, tag: T, value: &V) { + fn encode_tagged, V: Encodable>(&mut self, tag: T, value: &V) { let start_pos = self.position(); tag.encode(self); @@ -845,6 +836,20 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> { ((end_pos - start_pos) as u64).encode(self); } + pub fn encode_query_value>(&mut self, index: DepNodeIndex, value: &V) { + let index = SerializedDepNodeIndex::from_curr_for_serialization(index); + + self.query_values_index.push((index, AbsoluteBytePos::new(self.position()))); + self.encode_tagged(index, value); + } + + fn encode_side_effect(&mut self, index: DepNodeIndex, side_effect: &QuerySideEffect) { + let index = SerializedDepNodeIndex::from_curr_for_serialization(index); + + self.side_effects_index.push((index, AbsoluteBytePos::new(self.position()))); + self.encode_tagged(index, side_effect); + } + // copy&paste impl from rustc_metadata fn encode_symbol_or_byte_symbol( &mut self, diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 1c3f0f98ae178..02d3b0110cb8c 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_serialize = { path = "../rustc_serialize" } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b8aa125aaf96b..75da964c66c9e 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -2,18 +2,14 @@ use std::num::NonZero; use rustc_data_structures::unord::UnordMap; use rustc_hir::limit::Limit; -use rustc_index::Idx; use rustc_middle::bug; #[expect(unused_imports, reason = "used by doc comments")] use rustc_middle::dep_graph::DepKindVTable; use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, DepNodeKey, SerializedDepNodeIndex}; use rustc_middle::query::erase::{Erasable, Erased}; -use rustc_middle::query::on_disk_cache::{ - AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, -}; +use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder}; use rustc_middle::query::{QueryCache, QueryJobId, QueryMode, QueryVTable, erase}; use rustc_middle::ty::TyCtxt; -use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::DUMMY_SP; @@ -79,13 +75,9 @@ pub(crate) fn start_query( }) } -pub(crate) fn encode_query_values<'tcx>( - tcx: TyCtxt<'tcx>, - encoder: &mut CacheEncoder<'_, 'tcx>, - query_result_index: &mut EncodedDepNodeIndex, -) { +pub(crate) fn encode_query_values<'tcx>(tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>) { for_each_query_vtable!(CACHE_ON_DISK, tcx, |query| { - encode_query_values_inner(tcx, query, encoder, query_result_index) + encode_query_values_inner(tcx, query, encoder) }); } @@ -93,7 +85,6 @@ fn encode_query_values_inner<'a, 'tcx, C, V>( tcx: TyCtxt<'tcx>, query: &'tcx QueryVTable<'tcx, C>, encoder: &mut CacheEncoder<'a, 'tcx>, - query_result_index: &mut EncodedDepNodeIndex, ) where C: QueryCache>, V: Erasable + Encodable>, @@ -103,14 +94,7 @@ fn encode_query_values_inner<'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) { - let dep_node = SerializedDepNodeIndex::new(dep_node.index()); - - // Record position of the cache entry. - query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position()))); - - // Encode the type check tables with the `SerializedDepNodeIndex` - // as tag. - encoder.encode_tagged(dep_node, &erase::restore_val::(*value)); + encoder.encode_query_value::(dep_node, &erase::restore_val::(*value)); } }); } @@ -214,7 +198,7 @@ where // details. let value = tcx .dep_graph - .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index)); + .with_query_deserialization(|| on_disk_cache.try_load_query_value(tcx, prev_index)); prof_timer.finish_with_query_invocation_id(index.into()); From afffa7d6e3f969a58157e86732a25fe0bf8dc19c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 17 Mar 2026 15:27:00 +1100 Subject: [PATCH 2/4] Don't store current-session side effects in `OnDiskCache` Every other part of `OnDiskCache` deals with loading information from the _previous_ session, except for this one field. Moving it out to `QuerySystem` makes more sense, because that's also where query return values are stored (inside the caches in their vtables). --- .../rustc_incremental/src/persist/save.rs | 3 ++- compiler/rustc_middle/src/dep_graph/graph.rs | 12 ++-------- .../rustc_middle/src/query/on_disk_cache.rs | 23 ++++--------------- compiler/rustc_middle/src/query/plumbing.rs | 12 ++++++++-- compiler/rustc_query_impl/src/lib.rs | 1 + 5 files changed, 20 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 1de64bb6734d2..dc14a8c5e2ec4 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -6,6 +6,7 @@ use rustc_data_structures::sync::par_join; use rustc_middle::dep_graph::{ DepGraph, SerializedDepGraph, WorkProduct, WorkProductId, WorkProductMap, }; +use rustc_middle::query::on_disk_cache; use rustc_middle::ty::TyCtxt; use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::opaque::FileEncoder; @@ -82,7 +83,7 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { file_format::save_in(sess, query_cache_path, "query cache", |encoder| { tcx.sess.time("incr_comp_serialize_result_cache", || { - on_disk_cache.serialize(tcx, encoder) + on_disk_cache::OnDiskCache::serialize(tcx, encoder) }) }); }); diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 0f50abb827de2..fac79742657de 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -709,7 +709,7 @@ impl DepGraphData { // side effect. std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), ); - tcx.store_side_effect(dep_node_index, side_effect); + tcx.query_system.side_effects.borrow_mut().insert(dep_node_index, side_effect); dep_node_index } @@ -745,7 +745,7 @@ impl DepGraphData { } // This will just overwrite the same value for concurrent calls. - tcx.store_side_effect(dep_node_index, side_effect); + tcx.query_system.side_effects.borrow_mut().insert(dep_node_index, side_effect); }) } @@ -1560,12 +1560,4 @@ impl<'tcx> TyCtxt<'tcx> { .as_ref() .and_then(|c| c.load_side_effect(self, prev_dep_node_index)) } - - #[inline(never)] - #[cold] - fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { - if let Some(c) = self.query_system.on_disk_cache.as_ref() { - c.store_side_effect(dep_node_index, side_effect) - } - } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index b6409c1ea171e..9f7c5e1e7172e 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry; use std::sync::Arc; use std::{fmt, mem}; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::sync::{HashMapExt, Lock, RwLock}; use rustc_data_structures::unhash::UnhashMap; @@ -53,10 +53,6 @@ pub struct OnDiskCache { // The complete cache data in serialized form. serialized_data: RwLock>, - // Collects all `QuerySideEffect` created during the current compilation - // session. - current_side_effects: Lock>, - file_index_to_stable_id: FxHashMap, // Caches that are populated lazily during decoding. @@ -172,7 +168,6 @@ impl OnDiskCache { serialized_data: RwLock::new(Some(data)), file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), - current_side_effects: Default::default(), query_values_index: footer.query_values_index.into_iter().collect(), side_effects_index: footer.side_effects_index.into_iter().collect(), alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index), @@ -188,7 +183,6 @@ impl OnDiskCache { serialized_data: RwLock::new(None), file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), - current_side_effects: Default::default(), query_values_index: Default::default(), side_effects_index: Default::default(), alloc_decoding_state: AllocDecodingState::new(Vec::new()), @@ -205,7 +199,9 @@ impl OnDiskCache { *self.serialized_data.write() = None; } - pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult { + /// Serialize the current-session data that will be loaded by [`OnDiskCache`] + /// in a subsequent incremental compilation session. + pub fn serialize(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult { // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { // Allocate `SourceFileIndex`es. @@ -249,7 +245,7 @@ impl OnDiskCache { }); // Encode side effects. - for (&dep_node_index, side_effect) in self.current_side_effects.borrow().iter() { + for (&dep_node_index, side_effect) in tcx.query_system.side_effects.borrow().iter() { encoder.encode_side_effect(dep_node_index, side_effect); } @@ -339,15 +335,6 @@ impl OnDiskCache { side_effect } - /// Stores a `QuerySideEffect` emitted during the current compilation session. - /// Anything stored like this will be available via `load_side_effect` in - /// the next compilation session. - pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { - let mut current_side_effects = self.current_side_effects.borrow_mut(); - let prev = current_side_effects.insert(dep_node_index, side_effect); - debug_assert!(prev.is_none()); - } - /// Returns true if there is a disk-cached query return value for the given node. #[inline] pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool { diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 7d94d60523fb1..0977e56fce709 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -2,13 +2,14 @@ use std::fmt; use std::ops::Deref; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::hash_table::HashTable; use rustc_data_structures::sharded::Sharded; -use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; +use rustc_data_structures::sync::{AtomicU64, Lock, WorkerLocal}; use rustc_errors::Diag; use rustc_span::Span; -use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey}; use crate::query::on_disk_cache::OnDiskCache; @@ -151,6 +152,13 @@ pub struct QuerySystem<'tcx> { pub arenas: WorkerLocal>, pub query_vtables: QueryVTables<'tcx>, + /// Side-effect associated with each [`DepKind::SideEffect`] node in the + /// current incremental-compilation session. Side effects will be written + /// to disk, and loaded by [`OnDiskCache`] in the next session. + /// + /// Always empty if incremental compilation is off. + pub side_effects: Lock>, + /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by /// `DepGraph::try_mark_green()` and the query infrastructure. diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 2f69082db66e9..3a77d83cfd3e8 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -53,6 +53,7 @@ pub fn query_system<'tcx>( QuerySystem { arenas: Default::default(), query_vtables, + side_effects: Default::default(), on_disk_cache, local_providers, extern_providers, From db19c0c3ee2584ba8ac353862ab204b0b066ece2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 23 Mar 2026 15:59:45 +1100 Subject: [PATCH 3/4] Inline `TyCtxt::load_side_effect` into its only caller --- compiler/rustc_middle/src/dep_graph/graph.rs | 19 +++++++------------ .../rustc_middle/src/query/on_disk_cache.rs | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index fac79742657de..444d02521148c 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -718,7 +718,13 @@ impl DepGraphData { #[inline] fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { with_deps(TaskDepsRef::Ignore, || { - let side_effect = tcx.load_side_effect(prev_index).unwrap(); + let side_effect = tcx + .query_system + .on_disk_cache + .as_ref() + .unwrap() + .load_side_effect(tcx, prev_index) + .unwrap(); // Use `send_and_color` as `promote_node_and_deps_to_current` expects all // green dependencies. `send_and_color` will also prevent multiple nodes @@ -1549,15 +1555,4 @@ impl<'tcx> TyCtxt<'tcx> { fn is_eval_always(self, kind: DepKind) -> bool { self.dep_kind_vtable(kind).is_eval_always } - - // Interactions with on_disk_cache - fn load_side_effect( - self, - prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option { - self.query_system - .on_disk_cache - .as_ref() - .and_then(|c| c.load_side_effect(self, prev_dep_node_index)) - } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 9f7c5e1e7172e..466142ad6d593 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -325,7 +325,7 @@ impl OnDiskCache { } /// Loads a `QuerySideEffect` created during the previous compilation session. - pub fn load_side_effect( + pub(crate) fn load_side_effect( &self, tcx: TyCtxt<'_>, dep_node_index: SerializedDepNodeIndex, From ee151548176c71e29424de3cc3aec5f864968ef2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 23 Mar 2026 21:38:52 +1100 Subject: [PATCH 4/4] Remove an unhelpful assertion from `try_load_query_value` This assertion makes the method body a lot messier, and seems very unlikely to ever usefully fail. --- compiler/rustc_middle/src/query/on_disk_cache.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 466142ad6d593..b6fd30647f85f 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -351,9 +351,7 @@ impl OnDiskCache { where T: for<'a> Decodable>, { - let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_values_index); - debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index)); - opt_value + self.load_indexed(tcx, dep_node_index, &self.query_values_index) } fn load_indexed<'tcx, T>(