From b2441edaa3087b8329e86b7a1f95e84044b48cad Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 26 Sep 2026 17:17:04 +0000 Subject: [PATCH 1/9] Panic when trying to overwrite a file in the incr comp session We start with a fresh incr comp session dir, so an already existing file would mean that there is a conflict between two files produced by the same rustc instance. --- compiler/rustc_codegen_gcc/src/back/write.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 8 ++++++-- compiler/rustc_fs_util/src/lib.rs | 9 ++++++++- compiler/rustc_incremental/src/persist/work_product.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +++++- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index dcb4bcde38b60..701e8eb1ec098 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -174,7 +174,7 @@ pub(crate) fn codegen( EmitObj::Bitcode => { debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(err) = link_or_copy(&bc_out, &obj_out) { + if let Err(err) = link_or_copy(&bc_out, &obj_out, true /* allow_overwrite */) { dcx.emit_err(CopyBitcode { err }); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 7e71755ed4e70..a592d9e21b839 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1139,7 +1139,7 @@ pub(crate) fn codegen( EmitObj::Bitcode => { debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(err) = link_or_copy(&bc_out, &obj_out) { + if let Err(err) = link_or_copy(&bc_out, &obj_out, true /* allow_overwrite */) { dcx.emit_err(CopyBitcode { err }); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 0d7d85320d6fd..7b0bea8be2911 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -892,7 +892,11 @@ fn execute_copy_from_cache_work_item( source_file_in_incr_comp_dir, output_path.display() ); - match link_or_copy(&source_file_in_incr_comp_dir, &output_path) { + match link_or_copy( + &source_file_in_incr_comp_dir, + &output_path, + true, // allow_overwrite + ) { Ok(_) => Some(output_path), Err(error) => { dcx.emit_err(diagnostics::CopyPathBuf { @@ -2267,7 +2271,7 @@ pub(crate) fn submit_pre_lto_module_to_llvm( in_old_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename).unwrap(); let bitcode_path = in_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename); - match link_or_copy(&old_bitcode_path, &bitcode_path) { + match link_or_copy(&old_bitcode_path, &bitcode_path, false /* allow_overwrite */) { Ok(_) => {} Err(error) => { tcx.sess.dcx().emit_err(diagnostics::CopyPathBuf { diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index e21da4cdddf7d..d478f7bade448 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -59,7 +59,11 @@ pub enum LinkOrCopy { /// Copies `p` into `q`, preferring to use hard-linking if possible. /// The result indicates which of the two operations has been performed. -pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result { +pub fn link_or_copy, Q: AsRef>( + p: P, + q: Q, + allow_overwrite: bool, +) -> io::Result { // Creating a hard-link will fail if the destination path already exists. We could defensively // call remove_file in this function, but that pessimizes callers who can avoid such calls. // Incremental compilation calls this function a lot, and is able to avoid calls that @@ -74,6 +78,9 @@ pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result
  • { let _ = saved_files.insert(ext.to_string(), file_name); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c92b26e5c5b21..c1bbb969d679a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2621,7 +2621,11 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { let saved_path = &work_product.saved_files[OutputType::Metadata.extension()]; let source_file_in_incr_dir = &old_incr_comp_session_dir.join(saved_path); debug!("copying preexisting metadata from {source_file_in_incr_dir:?} to {path:?}"); - match rustc_fs_util::link_or_copy(&source_file_in_incr_dir, path) { + match rustc_fs_util::link_or_copy( + &source_file_in_incr_dir, + path, + true, // allow_overwrite + ) { Ok(_) => {} Err(err) => tcx.dcx().emit_fatal(FailCreateFileEncoder { err }), }; From 6b6b58a2a7008350a6b46caab7e78a92712682c5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 26 Sep 2026 17:40:21 +0000 Subject: [PATCH 2/9] Move IncrCompSession to rustc_middle --- .../rustc_codegen_cranelift/src/driver/aot.rs | 4 +- compiler/rustc_codegen_cranelift/src/lib.rs | 4 +- compiler/rustc_codegen_gcc/src/lib.rs | 8 +-- .../src/back/llvm_backend.rs | 8 +-- compiler/rustc_codegen_llvm/src/back/lto.rs | 4 +- compiler/rustc_codegen_ssa/src/back/write.rs | 6 ++- .../rustc_codegen_ssa/src/traits/backend.rs | 4 +- .../rustc_codegen_ssa/src/traits/write.rs | 4 +- compiler/rustc_incremental/src/persist/fs.rs | 4 +- .../rustc_incremental/src/persist/load.rs | 4 +- .../rustc_incremental/src/persist/save.rs | 4 +- .../src/persist/work_product.rs | 4 +- compiler/rustc_interface/src/passes.rs | 3 +- compiler/rustc_interface/src/queries.rs | 4 +- compiler/rustc_interface/src/util.rs | 4 +- compiler/rustc_middle/src/dep_graph/mod.rs | 51 +++++++++++++++++++ compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_session/src/session.rs | 49 ------------------ src/tools/miri/src/bin/miri.rs | 2 +- .../codegen-backend/auxiliary/the_backend.rs | 4 +- 20 files changed, 92 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index ce3741b582827..39eafdb1aae89 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -19,11 +19,11 @@ use rustc_codegen_ssa::traits::{ExtraBackendMethods, WriteBackendMethods}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::dep_graph::{BorrowedIncrCompSession, WorkProduct}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mono::{MonoItem, MonoItemData, Visibility}; +use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames, OutputType}; -use rustc_session::{BorrowedIncrCompSession, Session}; use rustc_span::Symbol; use crate::base::CodegenedFunction; diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index a30dd1c3ebef3..904e9ace4a976 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -42,9 +42,9 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo, TargetConfig, back}; use rustc_data_structures::unord::UnordSet; use rustc_log::tracing::info; -use rustc_middle::dep_graph::WorkProductMap; +use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; use rustc_session::config::{NATIVE_CPU, OutputFilenames}; -use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; +use rustc_session::{CodegenBackendInit, EarlySession, Session}; use rustc_span::{Symbol, sym}; use rustc_target::spec::{Arch, CfgAbi, Env, Os}; diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 414bff06866a8..45ca69e5b3d0f 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -89,12 +89,12 @@ use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodege use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; +use rustc_middle::dep_graph::{ + BorrowedIncrCompSession, IncrCompSession, WorkProduct, WorkProductMap, +}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames}; -use rustc_session::{ - BorrowedIncrCompSession, CodegenBackendInit, EarlySession, IncrCompSession, Session, -}; +use rustc_session::{CodegenBackendInit, EarlySession, Session}; use rustc_span::{Symbol, sym}; use rustc_target::spec::{RelocModel, TargetTuple}; use tempfile::TempDir; diff --git a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs index 69d63c52e4b88..0e9bc711f0498 100644 --- a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs +++ b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs @@ -20,12 +20,12 @@ use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodege use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; +use rustc_middle::dep_graph::{ + BorrowedIncrCompSession, IncrCompSession, WorkProduct, WorkProductMap, +}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; -use rustc_session::{ - BorrowedIncrCompSession, CodegenBackendInit, EarlySession, IncrCompSession, Session, -}; +use rustc_session::{CodegenBackendInit, EarlySession, Session}; use rustc_span::{Symbol, sym}; use rustc_target::spec::{RelocModel, TlsModel}; diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 8258c1f7c8d20..aab2f888b2f21 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -18,8 +18,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_middle::dep_graph::WorkProduct; -use rustc_session::{BorrowedIncrCompSession, config}; +use rustc_middle::dep_graph::{BorrowedIncrCompSession, WorkProduct}; +use rustc_session::config; use rustc_span::bug; use rustc_structures::SanitizerSet; use tracing::{debug, info}; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7b0bea8be2911..d37b7a90e8f04 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -20,12 +20,14 @@ use rustc_incremental::{ }; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::fs::copy_to_stdout; -use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; +use rustc_middle::dep_graph::{ + BorrowedIncrCompSession, IncrCompSession, WorkProduct, WorkProductMap, +}; use rustc_middle::ty::TyCtxt; +use rustc_session::Session; use rustc_session::config::{ self, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath, }; -use rustc_session::{BorrowedIncrCompSession, IncrCompSession, Session}; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, FileName, InnerSpan, Span, SyntaxContext, bug}; use rustc_structures::CrateType; diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index bf5d67c213573..dc72505b5c446 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -5,11 +5,11 @@ use rustc_ast::expand::allocator::AllocatorMethod; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::MetadataLoaderDyn; -use rustc_middle::dep_graph::WorkProductMap; +use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::config::{OutputFilenames, PrintRequest}; -use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; +use rustc_session::{CodegenBackendInit, EarlySession, Session}; use rustc_span::Symbol; use rustc_structures::CrateType; diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index 36bc0a68d882e..35bec4801eb9d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -4,8 +4,8 @@ use std::path::PathBuf; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::DiagCtxtHandle; -use rustc_middle::dep_graph::WorkProduct; -use rustc_session::{BorrowedIncrCompSession, Session, config}; +use rustc_middle::dep_graph::{BorrowedIncrCompSession, WorkProduct}; +use rustc_session::{Session, config}; use crate::back::lto::ThinModule; use crate::back::write::{ diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 038bddaa021d2..59058a0b1d097 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -107,9 +107,9 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; use rustc_fs_util::try_canonicalize; -use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::dep_graph::{IncrCompSession, WorkProduct}; use rustc_session::config::OutputType; -use rustc_session::{IncrCompSession, Session, StableCrateId}; +use rustc_session::{Session, StableCrateId}; use rustc_span::{Symbol, bug}; use tracing::debug; diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 76e0bf92c6f0f..dda119d621943 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -6,12 +6,12 @@ use std::sync::Arc; use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; -use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, IncrCompSession, SerializedDepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Encodable}; use rustc_session::config::IncrementalStateAssertion; -use rustc_session::{IncrCompSession, Session, StableCrateId}; +use rustc_session::{Session, StableCrateId}; use rustc_span::Symbol; use tracing::{debug, warn}; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 46f47d6c8623c..38bc7cd5b56b4 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,12 +1,12 @@ use std::fs; use rustc_data_structures::sync::par_join; -use rustc_middle::dep_graph::{DepGraph, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, IncrCompSession, WorkProductMap}; use rustc_middle::query::on_disk_cache; use rustc_middle::ty::TyCtxt; use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::opaque::FileEncoder; -use rustc_session::{IncrCompSession, Session}; +use rustc_session::Session; use tracing::debug; use super::data::*; diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 13958c0ef5f35..bb5524a29f50c 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -6,8 +6,8 @@ use std::path::Path; use rustc_data_structures::unord::UnordMap; use rustc_fs_util::link_or_copy; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_session::{IncrCompSession, Session}; +use rustc_middle::dep_graph::{IncrCompSession, WorkProduct, WorkProductId}; +use rustc_session::Session; use tracing::debug; use crate::diagnostics; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 6dc3f74f054f1..779b306163f3a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -29,6 +29,7 @@ use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_sto use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; +use rustc_middle::dep_graph::IncrCompSession; use rustc_middle::middle::resolve::{ResolverAstLowering, ResolverGlobalCtxt}; use rustc_middle::ty::{self, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; @@ -36,11 +37,11 @@ use rustc_parse::lexer::StripTokens; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_resolve::{Resolver, ResolverOutputs}; +use rustc_session::Session; use rustc_session::config::{Input, Offload, OutFileName, OutputFilenames, OutputType}; use rustc_session::diagnostics::feature_err; use rustc_session::output::{filename_for_input, invalid_output_for_target}; use rustc_session::search_paths::PathKind; -use rustc_session::{IncrCompSession, Session}; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, }; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 94cc1484586c8..dadda239d0131 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,10 +7,10 @@ use rustc_data_structures::svh::Svh; use rustc_errors::timings::TimingSection; use rustc_hir::def_id::LOCAL_CRATE; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, IncrCompSession, WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; +use rustc_session::Session; use rustc_session::config::{self, OutputFilenames, OutputType}; -use rustc_session::{IncrCompSession, Session}; use crate::diagnostics::FailedWritingFile; use crate::passes; diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 53f62e8d8c04c..e8f0e0d08d1b0 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -19,7 +19,7 @@ use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; use rustc_metadata::{DylibError, EncodedMetadata, load_symbol_from_dylib}; -use rustc_middle::dep_graph::WorkProductMap; +use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; use rustc_middle::ty::{CurrentGcx, TyCtxt}; use rustc_query_impl::{CollectActiveJobsKind, collect_active_query_jobs}; pub use rustc_session::config::DEFAULT_STACK_SIZE; @@ -27,7 +27,7 @@ use rustc_session::config::{ Cfg, Jobs, OptionsTargetModifiers, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple, }; -use rustc_session::{EarlyDiagCtxt, EarlySession, IncrCompSession, Session, filesearch}; +use rustc_session::{EarlyDiagCtxt, EarlySession, Session, filesearch}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; use rustc_span::{SessionGlobals, Symbol, sym}; diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index e63a281002f0d..ff9fbec6fc972 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,5 +1,8 @@ use std::panic; +use std::path::PathBuf; +use std::sync::Arc; +use rustc_data_structures::flock; use tracing::instrument; pub use self::dep_node::{DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label}; @@ -23,6 +26,54 @@ mod graph; mod retained; mod serialized; +/// Holds data on the current incremental compilation session, if there is one. +pub struct IncrCompSession { + /// The directory from which cached data of a previous session can be read. + pub old_session_directory: Option, + /// The directory to which cached data for the current session can be + /// written to. + pub new_session_directory: flock::LockedDir, + borrows: Arc<()>, +} + +impl IncrCompSession { + pub fn new( + old_session_directory: Option, + new_session_directory: flock::LockedDir, + ) -> Self { + IncrCompSession { old_session_directory, new_session_directory, borrows: Arc::new(()) } + } + + pub fn borrow(&self) -> BorrowedIncrCompSession { + BorrowedIncrCompSession { + old_session_directory: self.old_session_directory.as_deref().map(ToOwned::to_owned), + new_session_directory: (&*self.new_session_directory).to_owned(), + _borrows: Arc::clone(&self.borrows), + } + } +} + +impl Drop for IncrCompSession { + fn drop(&mut self) { + // Check that there are no worker threads remaining that use the incr + // comp session before we unlock the old and new session dir. If there + // does exist a worker thread, there is not much we can do, but at + // least we will unconditionally complain rather than the worker thread + // sometimes crashing depending on what other rustc instances run. + assert!( + Arc::strong_count(&self.borrows) == 1, + "Incr comp session dropped while there are still references", + ); + } +} + +/// A runtime tracked borrow of the incr comp session. Can be sent to worker threads. +pub struct BorrowedIncrCompSession { + pub old_session_directory: Option, + pub new_session_directory: PathBuf, + _borrows: Arc<()>, +} + /// Describes the contents of the fingerprint generated by a given query. /// /// This is mainly for determining whether and how we can reconstruct a key diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ef9020cf6ea56..5d375ef310d6e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -40,8 +40,8 @@ use rustc_index::IndexVec; use rustc_lint_defs::Lint; use rustc_lint_defs::builtin::UNUSED_FEATURES; use rustc_macros::Diagnostic; +use rustc_session::Session; use rustc_session::config::NextSolverConfig; -use rustc_session::{IncrCompSession, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, sym}; use rustc_structures::{CrateType, Limit}; @@ -55,7 +55,7 @@ use tracing::{debug, instrument}; use crate::arena::Arena; use crate::dep_graph::dep_node::make_metadata; -use crate::dep_graph::{DepGraph, DepNodeIndex}; +use crate::dep_graph::{DepGraph, DepNodeIndex, IncrCompSession}; use crate::hir::{ProjectedMaybeOwner, ProjectedOwnerInfo}; use crate::ich::StableHashState; use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind}; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b69c26639e7e8..642f08ca19727 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -7,7 +7,6 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::{env, io}; -use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{AppendOnlyVec, DynSend, DynSync, Lock}; @@ -1865,54 +1864,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } -/// Holds data on the current incremental compilation session, if there is one. -pub struct IncrCompSession { - /// The directory from which cached data of a previous session can be read. - pub old_session_directory: Option, - /// The directory to which cached data for the current session can be - /// written to. - pub new_session_directory: flock::LockedDir, - borrows: Arc<()>, -} - -impl IncrCompSession { - pub fn new( - old_session_directory: Option, - new_session_directory: flock::LockedDir, - ) -> Self { - IncrCompSession { old_session_directory, new_session_directory, borrows: Arc::new(()) } - } - - pub fn borrow(&self) -> BorrowedIncrCompSession { - BorrowedIncrCompSession { - old_session_directory: self.old_session_directory.as_deref().map(ToOwned::to_owned), - new_session_directory: (&*self.new_session_directory).to_owned(), - _borrows: Arc::clone(&self.borrows), - } - } -} - -impl Drop for IncrCompSession { - fn drop(&mut self) { - // Check that there are no worker threads remaining that use the incr - // comp session before we unlock the old and new session dir. If there - // does exist a worker thread, there is not much we can do, but at - // least we will unconditionally complain rather than the worker thread - // sometimes crashing depending on what other rustc instances run. - assert!( - Arc::strong_count(&self.borrows) == 1, - "Incr comp session dropped while there are still references", - ); - } -} - -/// A runtime tracked borrow of the incr comp session. Can be sent to worker threads. -pub struct BorrowedIncrCompSession { - pub old_session_directory: Option, - pub new_session_directory: PathBuf, - _borrows: Arc<()>, -} - /// A wrapper around an [`DiagCtxt`] that is used for early error emissions. pub struct EarlyDiagCtxt { dcx: DiagCtxt, diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index e3e2eef146ccc..279cc25344803 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -256,7 +256,7 @@ impl CodegenBackend for MiriCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - incr_comp_session: Option<&rustc_session::IncrCompSession>, + incr_comp_session: Option<&rustc_middle::dep_graph::IncrCompSession>, outputs: &rustc_session::config::OutputFilenames, crate_info: &CrateInfo, ) -> (CompiledModules, rustc_middle::dep_graph::WorkProductMap) { diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index a147e3ddf6942..9fb663b0d00a2 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -15,10 +15,10 @@ use std::any::Any; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo}; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::WorkProductMap; +use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; use rustc_middle::ty::TyCtxt; +use rustc_session::Session; use rustc_session::config::OutputFilenames; -use rustc_session::{IncrCompSession, Session}; struct TheBackend; From 15441b7db0b6172602fbd2202ecbb562c4eb618d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 27 Sep 2026 11:30:45 +0000 Subject: [PATCH 3/9] Pass a non-optional IncrCompSession to a couple of functions --- compiler/rustc_codegen_ssa/src/back/write.rs | 24 +++++++++-------- compiler/rustc_codegen_ssa/src/base.rs | 3 ++- compiler/rustc_incremental/src/persist/fs.rs | 11 ++------ .../rustc_incremental/src/persist/load.rs | 19 ++++--------- .../rustc_incremental/src/persist/save.rs | 14 ++++------ compiler/rustc_interface/src/passes.rs | 5 ++-- compiler/rustc_interface/src/queries.rs | 27 ++++++++++++------- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 +-- 8 files changed, 49 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d37b7a90e8f04..de3a76469b146 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -462,15 +462,17 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( incr_comp_session: Option<&IncrCompSession>, compiled_modules: &CompiledModules, ) -> WorkProductMap { - let mut work_products = WorkProductMap::default(); - - if sess.opts.incremental.is_none() || sess.opts.unstable_opts.disable_incr_comp_backend_caching - { - return work_products; + if sess.opts.unstable_opts.disable_incr_comp_backend_caching { + return WorkProductMap::default(); } + let Some(incr_comp_session) = incr_comp_session else { + return WorkProductMap::default(); + }; + let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir"); + let mut work_products = WorkProductMap::default(); for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { let mut files = Vec::new(); if let Some(object_file_path) = &module.object { @@ -493,7 +495,7 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( } let (id, product) = copy_cgu_workproduct_to_incr_comp_cache_dir( sess, - incr_comp_session.unwrap(), + incr_comp_session, &module.name, files.as_slice(), ); @@ -2264,19 +2266,19 @@ pub(crate) fn submit_post_lto_module_to_llvm( } pub(crate) fn submit_pre_lto_module_to_llvm( - tcx: TyCtxt<'_>, + sess: &Session, + incr_comp_session: &IncrCompSession, coordinator: &Coordinator, module: CachedModuleCodegen, ) { let filename = pre_lto_bitcode_filename(&module.name); - let old_bitcode_path = - in_old_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename).unwrap(); - let bitcode_path = in_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename); + let old_bitcode_path = in_old_incr_comp_dir_sess(incr_comp_session, &filename).unwrap(); + let bitcode_path = in_incr_comp_dir_sess(incr_comp_session, &filename); match link_or_copy(&old_bitcode_path, &bitcode_path, false /* allow_overwrite */) { Ok(_) => {} Err(error) => { - tcx.sess.dcx().emit_err(diagnostics::CopyPathBuf { + sess.dcx().emit_err(diagnostics::CopyPathBuf { source_file: old_bitcode_path, output_path: bitcode_path, error, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index ed2c05a20b9d4..4c98bebda1593 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -869,7 +869,8 @@ pub fn codegen_crate< } CguReuse::PreLto => { submit_pre_lto_module_to_llvm( - tcx, + tcx.sess, + tcx.incr_comp_session.unwrap(), &ongoing_codegen.coordinator, CachedModuleCodegen { name: cgu.name().to_string(), diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 59058a0b1d097..a73399f6be886 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -276,18 +276,11 @@ pub(crate) fn prepare_session_directory( /// This must not be called if there have been any compilation errors. pub fn finalize_session_directory( sess: &Session, - incr_comp_session: Option, - svh: Option, + mut incr_comp_session: IncrCompSession, + svh: Svh, ) { assert!(sess.dcx().has_errors_or_delayed_bugs().is_none()); - if sess.opts.incremental.is_none() { - return; - } - let mut incr_comp_session = incr_comp_session.unwrap(); - // The svh is always produced when incr. comp. is enabled. - let svh = svh.unwrap(); - let _timer = sess.timer("incr_comp_finalize_session_directory"); let incr_comp_session_dir = &*incr_comp_session.new_session_directory; diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index dda119d621943..4e5e989a18a67 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -118,30 +118,21 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe /// If we are not in incremental compilation mode, returns `None`. /// Otherwise, tries to load the query result cache from disk, /// creating an empty cache if it could not be loaded. -pub fn load_query_result_cache( - sess: &Session, - incr_comp_session: Option<&IncrCompSession>, -) -> Option { - if sess.opts.incremental.is_none() { - return None; - } - let incr_comp_session = incr_comp_session.unwrap(); - +pub fn load_query_result_cache(sess: &Session, incr_comp_session: &IncrCompSession) -> OnDiskCache { let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache"); let Some(path) = old_query_cache_path(incr_comp_session) else { - return Some(OnDiskCache::new_empty()); + return OnDiskCache::new_empty(); }; match file_format::open_incremental_file(sess, &path) { Ok(OpenFile { mmap, start_pos }) => { - let cache = OnDiskCache::new(sess, mmap, start_pos).unwrap_or_else(|()| { + OnDiskCache::new(sess, mmap, start_pos).unwrap_or_else(|()| { sess.dcx().emit_warn(diagnostics::CorruptFile { path: &path }); OnDiskCache::new_empty() - }); - Some(cache) + }) } Err(OpenFileError::NotFoundOrHeaderMismatch | OpenFileError::IoError { .. }) => { - Some(OnDiskCache::new_empty()) + OnDiskCache::new_empty() } } } diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 38bc7cd5b56b4..01446e5ce2f79 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -26,15 +26,14 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { debug!("save_dep_graph()"); tcx.dep_graph.with_ignore(|| { let sess = tcx.sess; - if sess.opts.incremental.is_none() { + let Some(incr_comp_session) = tcx.incr_comp_session else { return; - } + }; // This is going to be deleted in finalize_session_directory, so let's not create it. if sess.dcx().has_errors_or_delayed_bugs().is_some() { return; } - let incr_comp_session = tcx.incr_comp_session.unwrap(); let query_cache_path = query_cache_path(incr_comp_session); let dep_graph_path = dep_graph_path(incr_comp_session); let staging_dep_graph_path = staging_dep_graph_path(incr_comp_session); @@ -92,13 +91,10 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { /// Saves the work product index. pub fn save_work_product_index( sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: &IncrCompSession, dep_graph: &DepGraph, new_work_products: WorkProductMap, ) { - if sess.opts.incremental.is_none() { - return; - } // This is going to be deleted in finalize_session_directory, so let's not create it if sess.dcx().has_errors().is_some() { return; @@ -106,7 +102,7 @@ pub fn save_work_product_index( debug!("save_work_product_index()"); dep_graph.assert_ignored(); - let path = work_products_path(incr_comp_session.unwrap()); + let path = work_products_path(incr_comp_session); file_format::save_in(sess, path, "work product index", |mut e| { encode_work_product_index(&new_work_products, &mut e); e.finish() @@ -117,7 +113,7 @@ pub fn save_work_product_index( new_work_products.items().all(|(_, wp)| { wp.saved_files .items() - .all(|(_, path)| in_incr_comp_dir_sess(incr_comp_session.unwrap(), path).exists()) + .all(|(_, path)| in_incr_comp_dir_sess(incr_comp_session, path).exists()) }) }); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 779b306163f3a..8e7adda5e8a96 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -980,8 +980,9 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( // incr. comp. yet. dep_graph.assert_ignored(); - let query_result_on_disk_cache = - rustc_incremental::load_query_result_cache(sess, incr_comp_session.as_ref()); + let query_result_on_disk_cache = incr_comp_session.as_ref().map(|incr_comp_session| { + rustc_incremental::load_query_result_cache(sess, incr_comp_session) + }); let codegen_backend = &compiler.codegen_backend; let mut providers = *DEFAULT_QUERY_PROVIDERS; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index dadda239d0131..d9875c76a3825 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -87,21 +87,30 @@ impl Linker { let _timer = sess.timer("link"); - sess.time("serialize_work_products", || { - rustc_incremental::save_work_product_index( - sess, - incr_comp_session.as_ref(), - &self.dep_graph, - work_products, - ) - }); + if let Some(incr_comp_session) = &incr_comp_session { + sess.time("serialize_work_products", || { + rustc_incremental::save_work_product_index( + sess, + incr_comp_session, + &self.dep_graph, + work_products, + ) + }); + } let prof = sess.prof.clone(); prof.generic_activity("drop_dep_graph").run(move || drop(self.dep_graph)); // Now that we won't touch anything in the incremental compilation directory // any more, we can finalize it (which involves renaming it) - rustc_incremental::finalize_session_directory(sess, incr_comp_session, self.crate_hash); + if let Some(incr_comp_session) = incr_comp_session { + rustc_incremental::finalize_session_directory( + sess, + incr_comp_session, + // The svh is always produced when incr. comp. is enabled. + self.crate_hash.unwrap(), + ); + } // The `HostMetadata` offload pass only writes the kernel manifest. // Codegen was already skipped so there are no files to link. diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c1bbb969d679a..8e1070adcba71 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2610,8 +2610,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { let dep_node = tcx.metadata_dep_node(); // If the metadata dep-node is green, try to reuse the saved work product. - if tcx.dep_graph.is_fully_enabled() - && let incr_comp_session = tcx.incr_comp_session.unwrap() + if let Some(incr_comp_session) = tcx.incr_comp_session && let Some(old_incr_comp_session_dir) = &incr_comp_session.old_session_directory && let work_product_id = WorkProductId::from_cgu_name(WorkProduct::METADATA_WORKPRODUCT_CGU_NAME) From 8e0caad5852475feba7de5ca341eb58bf8a9fa4d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:03:02 +0000 Subject: [PATCH 4/9] Store list of produced work products in IncrCompSession --- compiler/rustc_codegen_cranelift/src/lib.rs | 6 +- compiler/rustc_codegen_gcc/src/lib.rs | 8 +-- .../src/back/llvm_backend.rs | 12 ++-- compiler/rustc_codegen_ssa/src/back/write.rs | 69 ++++++++----------- .../rustc_codegen_ssa/src/traits/backend.rs | 6 +- .../rustc_incremental/src/persist/save.rs | 5 +- .../src/persist/work_product.rs | 6 +- compiler/rustc_interface/src/queries.rs | 22 +++--- compiler/rustc_interface/src/util.rs | 8 +-- compiler/rustc_middle/src/dep_graph/mod.rs | 8 ++- src/tools/miri/src/bin/miri.rs | 4 +- .../codegen-backend/auxiliary/the_backend.rs | 11 ++- 12 files changed, 75 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 904e9ace4a976..dde5d919dab7f 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -42,7 +42,7 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo, TargetConfig, back}; use rustc_data_structures::unord::UnordSet; use rustc_log::tracing::info; -use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; +use rustc_middle::dep_graph::IncrCompSession; use rustc_session::config::{NATIVE_CPU, OutputFilenames}; use rustc_session::{CodegenBackendInit, EarlySession, Session}; use rustc_span::{Symbol, sym}; @@ -239,10 +239,10 @@ impl CodegenBackend for CraneliftCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: Option<&mut IncrCompSession>, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { + ) -> CompiledModules { ongoing_codegen .downcast::>() .unwrap() diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 45ca69e5b3d0f..bfdb84f80d740 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -89,9 +89,7 @@ use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodege use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_middle::dep_graph::{ - BorrowedIncrCompSession, IncrCompSession, WorkProduct, WorkProductMap, -}; +use rustc_middle::dep_graph::{BorrowedIncrCompSession, IncrCompSession, WorkProduct}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_session::{CodegenBackendInit, EarlySession, Session}; @@ -305,10 +303,10 @@ impl CodegenBackend for GccCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: Option<&mut IncrCompSession>, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { + ) -> CompiledModules { ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") diff --git a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs index 0e9bc711f0498..cbe7b38396785 100644 --- a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs +++ b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs @@ -20,9 +20,7 @@ use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodege use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{ - BorrowedIncrCompSession, IncrCompSession, WorkProduct, WorkProductMap, -}; +use rustc_middle::dep_graph::{BorrowedIncrCompSession, IncrCompSession, WorkProduct}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; use rustc_session::{CodegenBackendInit, EarlySession, Session}; @@ -368,11 +366,11 @@ impl CodegenBackend for LlvmCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: Option<&mut IncrCompSession>, outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { - let (compiled_modules, work_products) = ongoing_codegen + ) -> CompiledModules { + let compiled_modules = ongoing_codegen .downcast::>() .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box") .join(sess, incr_comp_session, crate_info); @@ -412,7 +410,7 @@ impl CodegenBackend for LlvmCodegenBackend { } } - (compiled_modules, work_products) + compiled_modules } fn link( diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index de3a76469b146..557b08ff77da2 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -20,9 +20,7 @@ use rustc_incremental::{ }; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::fs::copy_to_stdout; -use rustc_middle::dep_graph::{ - BorrowedIncrCompSession, IncrCompSession, WorkProduct, WorkProductMap, -}; +use rustc_middle::dep_graph::{BorrowedIncrCompSession, IncrCompSession, WorkProduct}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{ @@ -459,20 +457,15 @@ pub(crate) fn start_async_codegen( fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: &mut IncrCompSession, compiled_modules: &CompiledModules, -) -> WorkProductMap { +) { if sess.opts.unstable_opts.disable_incr_comp_backend_caching { - return WorkProductMap::default(); + return; } - let Some(incr_comp_session) = incr_comp_session else { - return WorkProductMap::default(); - }; - let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir"); - let mut work_products = WorkProductMap::default(); for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { let mut files = Vec::new(); if let Some(object_file_path) = &module.object { @@ -493,16 +486,13 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( if let Some(path) = &module.bytecode { files.push((OutputType::Bitcode.extension(), path.as_path())); } - let (id, product) = copy_cgu_workproduct_to_incr_comp_cache_dir( + copy_cgu_workproduct_to_incr_comp_cache_dir( sess, incr_comp_session, &module.name, files.as_slice(), ); - work_products.insert(id, product); } - - work_products } pub fn produce_final_output_artifacts( @@ -2124,9 +2114,9 @@ impl OngoingCodegen { pub fn join( self, sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: Option<&mut IncrCompSession>, crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { + ) -> CompiledModules { self.shared_emitter_main.check(sess, true); let maybe_lto_modules = sess.time("join_worker_thread", || match self.coordinator.join() { @@ -2145,25 +2135,26 @@ impl OngoingCodegen { let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); // Catch fatal errors to ensure shared_emitter_main.check() can emit the actual diagnostics - let compilation_output = catch_fatal_errors(|| match maybe_lto_modules { + let compiled_modules = catch_fatal_errors(|| match maybe_lto_modules { MaybeLtoModules::NoLto(compiled_modules) => { drop(shared_emitter); - let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir( - sess, - incr_comp_session, - &compiled_modules, - ); + if let Some(incr_comp_session) = incr_comp_session { + copy_all_cgu_workproducts_to_incr_comp_cache_dir( + sess, + incr_comp_session, + &compiled_modules, + ); + } - (compiled_modules, work_products) + compiled_modules } MaybeLtoModules::FatLto { cgcx, needs_fat_lto } => { let tm_factory = self.backend.target_machine_factory(sess, cgcx.opt_level); // FIXME cache local pre-LTO bitcode - let work_products = WorkProductMap::default(); - let compiled_modules = CompiledModules { + CompiledModules { modules: vec![do_fat_lto( sess, &cgcx, @@ -2174,9 +2165,7 @@ impl OngoingCodegen { needs_fat_lto, )], allocator_module: None, - }; - - (compiled_modules, work_products) + } } MaybeLtoModules::ThinLto { cgcx, needs_thin_lto } => { let tm_factory = self.backend.target_machine_factory(sess, cgcx.opt_level); @@ -2185,7 +2174,7 @@ impl OngoingCodegen { modules: do_thin_lto::( &cgcx, &sess.prof, - incr_comp_session.map(|incr_comp_session| incr_comp_session.borrow()), + incr_comp_session.as_deref().map(IncrCompSession::borrow), shared_emitter, tm_factory, &crate_info.exported_symbols_for_lto, @@ -2198,13 +2187,15 @@ impl OngoingCodegen { // FIXME include pre-LTO bitcode in workproduct tracking // FIXME add separate incr comp session for post-LTO outputs to use during link step - let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir( - sess, - incr_comp_session, - &compiled_modules, - ); + if let Some(incr_comp_session) = incr_comp_session { + copy_all_cgu_workproducts_to_incr_comp_cache_dir( + sess, + incr_comp_session, + &compiled_modules, + ); + } - (compiled_modules, work_products) + compiled_modules } }); @@ -2212,8 +2203,8 @@ impl OngoingCodegen { sess.dcx().abort_if_errors(); - let (mut compiled_modules, work_products) = - compilation_output.expect("fatal error emitted but not sent to SharedEmitter"); + let mut compiled_modules = + compiled_modules.expect("fatal error emitted but not sent to SharedEmitter"); // Regardless of what order these modules completed in, report them to // the backend in the same order every time to ensure that we're handing @@ -2222,7 +2213,7 @@ impl OngoingCodegen { produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames); - (compiled_modules, work_products) + compiled_modules } pub(crate) fn codegen_finished(&self, tcx: TyCtxt<'_>) { diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index dc72505b5c446..5c387d1353f00 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -5,7 +5,7 @@ use rustc_ast::expand::allocator::AllocatorMethod; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::MetadataLoaderDyn; -use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; +use rustc_middle::dep_graph::IncrCompSession; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::config::{OutputFilenames, PrintRequest}; @@ -115,10 +115,10 @@ pub trait CodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - incr_comp_session: Option<&IncrCompSession>, + incr_comp_session: Option<&mut IncrCompSession>, outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap); + ) -> CompiledModules; /// This is called on the returned [`CompiledModules`] from [`join_codegen`](Self::join_codegen). fn link( diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 01446e5ce2f79..96722ffea105f 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -93,7 +93,6 @@ pub fn save_work_product_index( sess: &Session, incr_comp_session: &IncrCompSession, dep_graph: &DepGraph, - new_work_products: WorkProductMap, ) { // This is going to be deleted in finalize_session_directory, so let's not create it if sess.dcx().has_errors().is_some() { @@ -104,13 +103,13 @@ pub fn save_work_product_index( dep_graph.assert_ignored(); let path = work_products_path(incr_comp_session); file_format::save_in(sess, path, "work product index", |mut e| { - encode_work_product_index(&new_work_products, &mut e); + encode_work_product_index(&incr_comp_session.new_work_products, &mut e); e.finish() }); // Check that we did not delete one of the current work-products: debug_assert!({ - new_work_products.items().all(|(_, wp)| { + incr_comp_session.new_work_products.items().all(|(_, wp)| { wp.saved_files .items() .all(|(_, path)| in_incr_comp_dir_sess(incr_comp_session, path).exists()) diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index bb5524a29f50c..ce2764da212c9 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -19,10 +19,10 @@ use crate::persist::fs::*; /// Panics when incr comp is disabled. pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, - incr_comp_session: &IncrCompSession, + incr_comp_session: &mut IncrCompSession, cgu_name: &str, files: &[(&'static str, &Path)], -) -> (WorkProductId, WorkProduct) { +) { debug!(?cgu_name, ?files); assert!(sess.opts.incremental.is_some()); @@ -47,5 +47,5 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files }; debug!(?work_product); let work_product_id = WorkProductId::from_cgu_name(cgu_name); - (work_product_id, work_product) + incr_comp_session.new_work_products.insert(work_product_id, work_product); } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index d9875c76a3825..873f42448cb1e 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,7 +7,7 @@ use rustc_data_structures::svh::Svh; use rustc_errors::timings::TimingSection; use rustc_hir::def_id::LOCAL_CRATE; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{DepGraph, IncrCompSession, WorkProduct, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, IncrCompSession, WorkProduct}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{self, OutputFilenames, OutputType}; @@ -49,18 +49,18 @@ impl Linker { pub fn link( self, sess: &Session, - incr_comp_session: Option, + mut incr_comp_session: Option, codegen_backend: &dyn CodegenBackend, ) { - let (compiled_modules, mut work_products) = sess.time("finish_ongoing_codegen", || { + let compiled_modules = sess.time("finish_ongoing_codegen", || { match self.ongoing_codegen.downcast::() { // This was a check only build - Ok(compiled_modules) => (*compiled_modules, WorkProductMap::default()), + Ok(compiled_modules) => *compiled_modules, Err(ongoing_codegen) => codegen_backend.join_codegen( ongoing_codegen, sess, - incr_comp_session.as_ref(), + incr_comp_session.as_mut(), &self.output_filenames, &self.crate_info, ), @@ -72,13 +72,12 @@ impl Linker { if sess.opts.incremental.is_some() && let Some(path) = self.metadata.path() { - let (id, product) = rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, - incr_comp_session.as_ref().unwrap(), + incr_comp_session.as_mut().unwrap(), WorkProduct::METADATA_WORKPRODUCT_CGU_NAME, &[(OutputType::Metadata.extension(), path)], ); - work_products.insert(id, product); } if let Some(guar) = sess.dcx().has_errors_or_delayed_bugs() { @@ -89,12 +88,7 @@ impl Linker { if let Some(incr_comp_session) = &incr_comp_session { sess.time("serialize_work_products", || { - rustc_incremental::save_work_product_index( - sess, - incr_comp_session, - &self.dep_graph, - work_products, - ) + rustc_incremental::save_work_product_index(sess, incr_comp_session, &self.dep_graph) }); } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index e8f0e0d08d1b0..a97c88d4cc964 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -19,7 +19,7 @@ use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; use rustc_metadata::{DylibError, EncodedMetadata, load_symbol_from_dylib}; -use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; +use rustc_middle::dep_graph::IncrCompSession; use rustc_middle::ty::{CurrentGcx, TyCtxt}; use rustc_query_impl::{CollectActiveJobsKind, collect_active_query_jobs}; pub use rustc_session::config::DEFAULT_STACK_SIZE; @@ -469,11 +469,11 @@ impl CodegenBackend for DummyCodegenBackend { &self, ongoing_codegen: Box, _sess: &Session, - _incr_comp_session: Option<&IncrCompSession>, + _incr_comp_session: Option<&mut IncrCompSession>, _outputs: &OutputFilenames, _crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { - (*ongoing_codegen.downcast().unwrap(), WorkProductMap::default()) + ) -> CompiledModules { + *ongoing_codegen.downcast().unwrap() } fn link( diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index ff9fbec6fc972..8a049911675ce 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -33,6 +33,7 @@ pub struct IncrCompSession { /// The directory to which cached data for the current session can be /// written to. pub new_session_directory: flock::LockedDir, + pub new_work_products: WorkProductMap, borrows: Arc<()>, } @@ -41,7 +42,12 @@ impl IncrCompSession { old_session_directory: Option, new_session_directory: flock::LockedDir, ) -> Self { - IncrCompSession { old_session_directory, new_session_directory, borrows: Arc::new(()) } + IncrCompSession { + old_session_directory, + new_session_directory, + new_work_products: WorkProductMap::default(), + borrows: Arc::new(()), + } } pub fn borrow(&self) -> BorrowedIncrCompSession { diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 279cc25344803..3b51b43db10ca 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -256,10 +256,10 @@ impl CodegenBackend for MiriCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - incr_comp_session: Option<&rustc_middle::dep_graph::IncrCompSession>, + incr_comp_session: Option<&mut rustc_middle::dep_graph::IncrCompSession>, outputs: &rustc_session::config::OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, rustc_middle::dep_graph::WorkProductMap) { + ) -> CompiledModules { self.dummy.join_codegen(ongoing_codegen, sess, incr_comp_session, outputs, crate_info) } diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 9fb663b0d00a2..5cfcb5df1cb56 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -15,7 +15,7 @@ use std::any::Any; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo}; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; +use rustc_middle::dep_graph::IncrCompSession; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::OutputFilenames; @@ -39,14 +39,13 @@ impl CodegenBackend for TheBackend { &self, ongoing_codegen: Box, _sess: &Session, - _incr_comp_session: Option<&IncrCompSession>, + _incr_comp_session: Option<&mut IncrCompSession>, _outputs: &OutputFilenames, _crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { - let codegen_results = ongoing_codegen + ) -> CompiledModules { + *ongoing_codegen .downcast::() - .expect("in join_codegen: ongoing_codegen is not a CompiledModules"); - (*codegen_results, WorkProductMap::default()) + .expect("in join_codegen: ongoing_codegen is not a CompiledModules") } fn link( From 966203b62ac49f9bdf4bf1619b361bca4bfe3bf2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 29 Oct 2026 15:11:46 +0000 Subject: [PATCH 5/9] Call save_work_product_index from finalize_session_directory --- compiler/rustc_incremental/src/lib.rs | 2 +- compiler/rustc_incremental/src/persist/fs.rs | 4 ++++ compiler/rustc_incremental/src/persist/mod.rs | 1 - compiler/rustc_incremental/src/persist/save.rs | 16 +++------------- compiler/rustc_interface/src/queries.rs | 6 ------ 5 files changed, 8 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index b5470d224ffbd..92603d6ad3f07 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -12,7 +12,7 @@ mod persist; pub use persist::{ copy_cgu_workproduct_to_incr_comp_cache_dir, finalize_session_directory, in_incr_comp_dir_sess, - in_old_incr_comp_dir_sess, load_query_result_cache, save_work_product_index, setup_dep_graph, + in_old_incr_comp_dir_sess, load_query_result_cache, setup_dep_graph, }; use rustc_middle::util::Providers; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index a73399f6be886..af30346fdaba5 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -281,6 +281,10 @@ pub fn finalize_session_directory( ) { assert!(sess.dcx().has_errors_or_delayed_bugs().is_none()); + sess.time("serialize_work_products", || { + crate::persist::save::save_work_product_index(sess, &incr_comp_session) + }); + let _timer = sess.timer("incr_comp_finalize_session_directory"); let incr_comp_session_dir = &*incr_comp_session.new_session_directory; diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index fb318357b26cb..3b056ff4ddec0 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -13,5 +13,4 @@ mod work_product; pub use fs::{finalize_session_directory, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess}; pub use load::{load_query_result_cache, setup_dep_graph}; pub(crate) use save::save_dep_graph; -pub use save::save_work_product_index; pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 96722ffea105f..335f75a88acf4 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,7 +1,7 @@ use std::fs; use rustc_data_structures::sync::par_join; -use rustc_middle::dep_graph::{DepGraph, IncrCompSession, WorkProductMap}; +use rustc_middle::dep_graph::{IncrCompSession, WorkProductMap}; use rustc_middle::query::on_disk_cache; use rustc_middle::ty::TyCtxt; use rustc_serialize::Encodable as RustcEncodable; @@ -15,7 +15,7 @@ use super::{clean, file_format}; use crate::assert_dep_graph::assert_dep_graph; use crate::diagnostics; -/// Saves and writes the [`DepGraph`] to the file system. +/// Saves and writes the [`DepGraph`](rustc_middle::dep_graph::DepGraph) to the file system. /// /// This function saves both the dep-graph and the query result cache, /// and drops the result cache. @@ -89,18 +89,8 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { } /// Saves the work product index. -pub fn save_work_product_index( - sess: &Session, - incr_comp_session: &IncrCompSession, - dep_graph: &DepGraph, -) { - // This is going to be deleted in finalize_session_directory, so let's not create it - if sess.dcx().has_errors().is_some() { - return; - } - +pub(super) fn save_work_product_index(sess: &Session, incr_comp_session: &IncrCompSession) { debug!("save_work_product_index()"); - dep_graph.assert_ignored(); let path = work_products_path(incr_comp_session); file_format::save_in(sess, path, "work product index", |mut e| { encode_work_product_index(&incr_comp_session.new_work_products, &mut e); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 873f42448cb1e..d1fa40079180e 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -86,12 +86,6 @@ impl Linker { let _timer = sess.timer("link"); - if let Some(incr_comp_session) = &incr_comp_session { - sess.time("serialize_work_products", || { - rustc_incremental::save_work_product_index(sess, incr_comp_session, &self.dep_graph) - }); - } - let prof = sess.prof.clone(); prof.generic_activity("drop_dep_graph").run(move || drop(self.dep_graph)); From 9cb4d6630fce506f8debfa0ede159f2ca00b5587 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 29 Oct 2026 15:51:52 +0000 Subject: [PATCH 6/9] Move SerializedWorkProduct to persist/work_product.rs --- compiler/rustc_incremental/src/persist/data.rs | 13 ------------- compiler/rustc_incremental/src/persist/load.rs | 2 +- compiler/rustc_incremental/src/persist/mod.rs | 1 - compiler/rustc_incremental/src/persist/save.rs | 2 +- .../rustc_incremental/src/persist/work_product.rs | 10 ++++++++++ 5 files changed, 12 insertions(+), 16 deletions(-) delete mode 100644 compiler/rustc_incremental/src/persist/data.rs diff --git a/compiler/rustc_incremental/src/persist/data.rs b/compiler/rustc_incremental/src/persist/data.rs deleted file mode 100644 index d962dc866f43b..0000000000000 --- a/compiler/rustc_incremental/src/persist/data.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! The data that we will serialize and deserialize. - -use rustc_macros::{Decodable, Encodable}; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; - -#[derive(Debug, Encodable, Decodable)] -pub(crate) struct SerializedWorkProduct { - /// node that produced the work-product - pub id: WorkProductId, - - /// work-product data itself - pub work_product: WorkProduct, -} diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 4e5e989a18a67..7b6b8c7b27b6c 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -15,9 +15,9 @@ use rustc_session::{Session, StableCrateId}; use rustc_span::Symbol; use tracing::{debug, warn}; -use super::data::*; use super::file_format; use super::fs::*; +use super::work_product::SerializedWorkProduct; use crate::diagnostics; use crate::persist::file_format::{OpenFile, OpenFileError}; diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index 3b056ff4ddec0..e101d8df8e2e7 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -3,7 +3,6 @@ //! various HIR nodes. mod clean; -mod data; mod file_format; mod fs; mod load; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 335f75a88acf4..c6cc33e9bb050 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -9,8 +9,8 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::Session; use tracing::debug; -use super::data::*; use super::fs::*; +use super::work_product::SerializedWorkProduct; use super::{clean, file_format}; use crate::assert_dep_graph::assert_dep_graph; use crate::diagnostics; diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index ce2764da212c9..822faba2ca170 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -6,6 +6,7 @@ use std::path::Path; use rustc_data_structures::unord::UnordMap; use rustc_fs_util::link_or_copy; +use rustc_macros::{Decodable, Encodable}; use rustc_middle::dep_graph::{IncrCompSession, WorkProduct, WorkProductId}; use rustc_session::Session; use tracing::debug; @@ -49,3 +50,12 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let work_product_id = WorkProductId::from_cgu_name(cgu_name); incr_comp_session.new_work_products.insert(work_product_id, work_product); } + +#[derive(Debug, Encodable, Decodable)] +pub(crate) struct SerializedWorkProduct { + /// node that produced the work-product + pub id: WorkProductId, + + /// work-product data itself + pub work_product: WorkProduct, +} From 59ad666976391a267d7dde03a1eb336b60219e13 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 29 Oct 2026 15:58:53 +0000 Subject: [PATCH 7/9] Merge LoadResult::{DataOutOfData, IoError} --- .../rustc_incremental/src/persist/load.rs | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 7b6b8c7b27b6c..5732f5229a898 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -1,7 +1,5 @@ //! Code to load the dep-graph from files. -use std::io; -use std::path::PathBuf; use std::sync::Arc; use rustc_data_structures::unord::UnordMap; @@ -26,10 +24,9 @@ use crate::persist::file_format::{OpenFile, OpenFileError}; enum LoadResult { /// Loading was successful. Ok { prev_graph: Arc, prev_work_products: WorkProductMap }, - /// The file either didn't exist or was produced by an incompatible compiler version. - DataOutOfDate, - /// Loading failed due to an unexpected I/O error. - IoError { path: PathBuf, err: io::Error }, + /// A file was produced by an incompatible compiler version, didn't exist or for some + /// other reason couldn't be used. + Error, } fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadResult { @@ -40,14 +37,14 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. let Some(path) = old_dep_graph_path(incr_comp_session) else { - return LoadResult::DataOutOfDate; + return LoadResult::Error; }; let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = UnordMap::default(); let Some(work_products_path) = old_work_products_path(incr_comp_session) else { - return LoadResult::DataOutOfDate; + return LoadResult::Error; }; if let Ok(OpenFile { mmap, start_pos }) = @@ -56,7 +53,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe // Decode the list of work_products let Ok(mut work_product_decoder) = MemDecoder::new(&mmap[..], start_pos) else { sess.dcx().emit_warn(diagnostics::CorruptFile { path: &work_products_path }); - return LoadResult::DataOutOfDate; + return LoadResult::Error; }; let work_products: Vec = Decodable::decode(&mut work_product_decoder); @@ -75,7 +72,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe prev_work_products.insert(swp.id, swp.work_product); } else { debug!("reconcile_work_products: some file for {:?} does not exist", swp); - return LoadResult::DataOutOfDate; + return LoadResult::Error; } } } @@ -83,12 +80,15 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe let _prof_timer = sess.prof.generic_activity("incr_comp_load_dep_graph"); match file_format::open_incremental_file(sess, &path) { - Err(OpenFileError::NotFoundOrHeaderMismatch) => LoadResult::DataOutOfDate, - Err(OpenFileError::IoError { err }) => LoadResult::IoError { path: path.to_owned(), err }, + Err(OpenFileError::NotFoundOrHeaderMismatch) => LoadResult::Error, + Err(OpenFileError::IoError { err }) => { + sess.dcx().emit_warn(diagnostics::LoadDepGraph { path, err }); + LoadResult::Error + } Ok(OpenFile { mmap, start_pos }) => { let Ok(mut decoder) = MemDecoder::new(&mmap, start_pos) else { sess.dcx().emit_warn(diagnostics::CorruptFile { path: &path }); - return LoadResult::DataOutOfDate; + return LoadResult::Error; }; let prev_commandline_args_hash = Hash64::decode(&mut decoder); @@ -103,7 +103,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe debug!("load_dep_graph_new: differing commandline arg hashes"); // No need to do any further work - return LoadResult::DataOutOfDate; + return LoadResult::Error; } let prev_graph = SerializedDepGraph::decode(&mut decoder, &sess.prof); @@ -146,7 +146,7 @@ fn maybe_assert_incr_state(sess: &Session, load_result: &LoadResult) { // Match exhaustively to make sure we don't miss any cases. let loaded = match load_result { LoadResult::Ok { .. } => true, - LoadResult::DataOutOfDate | LoadResult::IoError { .. } => false, + LoadResult::Error => false, }; match assertion { @@ -195,12 +195,7 @@ pub fn setup_dep_graph( maybe_assert_incr_state(sess, &load_result); let (prev_graph, prev_work_products) = match load_result { - LoadResult::IoError { path, err } => { - sess.dcx().emit_warn(diagnostics::LoadDepGraph { path, err }); - invalidate_old_session_dir(sess, &mut incr_comp_session); - Default::default() - } - LoadResult::DataOutOfDate => { + LoadResult::Error => { invalidate_old_session_dir(sess, &mut incr_comp_session); Default::default() } From 7a79cf036f0603deebf9f1c13a15831483e9858c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 29 Oct 2026 16:04:04 +0000 Subject: [PATCH 8/9] Replace LoadResult with a plain Result --- .../rustc_incremental/src/persist/load.rs | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 5732f5229a898..cf1c46ec251da 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -19,17 +19,14 @@ use super::work_product::SerializedWorkProduct; use crate::diagnostics; use crate::persist::file_format::{OpenFile, OpenFileError}; -#[derive(Debug)] -/// Represents the result of an attempt to load incremental compilation data. -enum LoadResult { - /// Loading was successful. - Ok { prev_graph: Arc, prev_work_products: WorkProductMap }, - /// A file was produced by an incompatible compiler version, didn't exist or for some - /// other reason couldn't be used. - Error, -} - -fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadResult { +/// Load the old dep graph and work product index. +/// +/// Returns Err(()) if a file was produced by an incompatible compiler version, didn't +/// exist or for some other reason couldn't be used. +fn load_dep_graph( + sess: &Session, + incr_comp_session: &IncrCompSession, +) -> Result<(Arc, WorkProductMap), ()> { assert!(sess.opts.incremental.is_some()); let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph"); @@ -37,14 +34,14 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. let Some(path) = old_dep_graph_path(incr_comp_session) else { - return LoadResult::Error; + return Err(()); }; let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = UnordMap::default(); let Some(work_products_path) = old_work_products_path(incr_comp_session) else { - return LoadResult::Error; + return Err(()); }; if let Ok(OpenFile { mmap, start_pos }) = @@ -53,7 +50,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe // Decode the list of work_products let Ok(mut work_product_decoder) = MemDecoder::new(&mmap[..], start_pos) else { sess.dcx().emit_warn(diagnostics::CorruptFile { path: &work_products_path }); - return LoadResult::Error; + return Err(()); }; let work_products: Vec = Decodable::decode(&mut work_product_decoder); @@ -72,7 +69,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe prev_work_products.insert(swp.id, swp.work_product); } else { debug!("reconcile_work_products: some file for {:?} does not exist", swp); - return LoadResult::Error; + return Err(()); } } } @@ -80,15 +77,15 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe let _prof_timer = sess.prof.generic_activity("incr_comp_load_dep_graph"); match file_format::open_incremental_file(sess, &path) { - Err(OpenFileError::NotFoundOrHeaderMismatch) => LoadResult::Error, + Err(OpenFileError::NotFoundOrHeaderMismatch) => Err(()), Err(OpenFileError::IoError { err }) => { sess.dcx().emit_warn(diagnostics::LoadDepGraph { path, err }); - LoadResult::Error + Err(()) } Ok(OpenFile { mmap, start_pos }) => { let Ok(mut decoder) = MemDecoder::new(&mmap, start_pos) else { sess.dcx().emit_warn(diagnostics::CorruptFile { path: &path }); - return LoadResult::Error; + return Err(()); }; let prev_commandline_args_hash = Hash64::decode(&mut decoder); @@ -103,12 +100,12 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe debug!("load_dep_graph_new: differing commandline arg hashes"); // No need to do any further work - return LoadResult::Error; + return Err(()); } let prev_graph = SerializedDepGraph::decode(&mut decoder, &sess.prof); - LoadResult::Ok { prev_graph, prev_work_products } + Ok((prev_graph, prev_work_products)) } } } @@ -139,16 +136,10 @@ pub fn load_query_result_cache(sess: &Session, incr_comp_session: &IncrCompSessi /// Emits a fatal error if the assertion in `-Zassert-incr-state` doesn't match /// the outcome of trying to load previous-session state. -fn maybe_assert_incr_state(sess: &Session, load_result: &LoadResult) { +fn maybe_assert_incr_state(sess: &Session, loaded: bool) { // Return immediately if there's nothing to assert. let Some(assertion) = sess.opts.unstable_opts.assert_incr_state else { return }; - // Match exhaustively to make sure we don't miss any cases. - let loaded = match load_result { - LoadResult::Ok { .. } => true, - LoadResult::Error => false, - }; - match assertion { IncrementalStateAssertion::Loaded => { if !loaded { @@ -192,14 +183,14 @@ pub fn setup_dep_graph( }); // Emit a fatal error if `-Zassert-incr-state` is present and unsatisfied. - maybe_assert_incr_state(sess, &load_result); + maybe_assert_incr_state(sess, load_result.is_ok()); let (prev_graph, prev_work_products) = match load_result { - LoadResult::Error => { + Ok((prev_graph, prev_work_products)) => (prev_graph, prev_work_products), + Err(()) => { invalidate_old_session_dir(sess, &mut incr_comp_session); Default::default() } - LoadResult::Ok { prev_graph, prev_work_products } => (prev_graph, prev_work_products), }; // Stream the dep-graph to an alternate file, to avoid overwriting anything in case of errors. From 1ce77301506de5453023c1e1d3c3e78f89df1891 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 29 Oct 2026 16:07:01 +0000 Subject: [PATCH 9/9] Extract load_work_product_index out of load_dep_graph --- .../rustc_incremental/src/persist/load.rs | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index cf1c46ec251da..63c950b27de08 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -2,7 +2,6 @@ use std::sync::Arc; -use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; use rustc_middle::dep_graph::{DepGraph, IncrCompSession, SerializedDepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache::OnDiskCache; @@ -38,41 +37,7 @@ fn load_dep_graph( }; let expected_hash = sess.opts.dep_tracking_hash(false); - let mut prev_work_products = UnordMap::default(); - - let Some(work_products_path) = old_work_products_path(incr_comp_session) else { - return Err(()); - }; - - if let Ok(OpenFile { mmap, start_pos }) = - file_format::open_incremental_file(sess, &work_products_path) - { - // Decode the list of work_products - let Ok(mut work_product_decoder) = MemDecoder::new(&mmap[..], start_pos) else { - sess.dcx().emit_warn(diagnostics::CorruptFile { path: &work_products_path }); - return Err(()); - }; - let work_products: Vec = - Decodable::decode(&mut work_product_decoder); - - for swp in work_products { - let all_files_exist = swp.work_product.saved_files.items().all(|(_, path)| { - let exists = in_old_incr_comp_dir_sess(incr_comp_session, path).unwrap().exists(); - if !exists && sess.opts.unstable_opts.incremental_info { - eprintln!("incremental: could not find file for work product: {path}",); - } - exists - }); - - if all_files_exist { - debug!("reconcile_work_products: all files for {:?} exist", swp); - prev_work_products.insert(swp.id, swp.work_product); - } else { - debug!("reconcile_work_products: some file for {:?} does not exist", swp); - return Err(()); - } - } - } + let prev_work_products = load_work_product_index(sess, incr_comp_session)?; let _prof_timer = sess.prof.generic_activity("incr_comp_load_dep_graph"); @@ -110,6 +75,49 @@ fn load_dep_graph( } } +fn load_work_product_index( + sess: &Session, + incr_comp_session: &IncrCompSession, +) -> Result { + let mut prev_work_products = WorkProductMap::default(); + + let Some(work_products_path) = old_work_products_path(incr_comp_session) else { + return Err(()); + }; + + if let Ok(OpenFile { mmap, start_pos }) = + file_format::open_incremental_file(sess, &work_products_path) + { + // Decode the list of work_products + let Ok(mut work_product_decoder) = MemDecoder::new(&mmap[..], start_pos) else { + sess.dcx().emit_warn(diagnostics::CorruptFile { path: &work_products_path }); + return Err(()); + }; + let work_products: Vec = + Decodable::decode(&mut work_product_decoder); + + for swp in work_products { + let all_files_exist = swp.work_product.saved_files.items().all(|(_, path)| { + let exists = in_old_incr_comp_dir_sess(incr_comp_session, path).unwrap().exists(); + if !exists && sess.opts.unstable_opts.incremental_info { + eprintln!("incremental: could not find file for work product: {path}",); + } + exists + }); + + if all_files_exist { + debug!("reconcile_work_products: all files for {:?} exist", swp); + prev_work_products.insert(swp.id, swp.work_product); + } else { + debug!("reconcile_work_products: some file for {:?} does not exist", swp); + return Err(()); + } + } + } + + Ok(prev_work_products) +} + /// Attempts to load the query result cache from disk /// /// If we are not in incremental compilation mode, returns `None`.