rustc_incremental/persist/
load.rs1use std::io;
4use std::path::PathBuf;
5use std::sync::Arc;
6
7use rustc_data_structures::unord::UnordMap;
8use rustc_hashes::Hash64;
9use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProductMap};
10use rustc_middle::query::on_disk_cache::OnDiskCache;
11use rustc_serialize::opaque::{FileEncoder, MemDecoder};
12use rustc_serialize::{Decodable, Encodable};
13use rustc_session::config::IncrementalStateAssertion;
14use rustc_session::{Session, StableCrateId};
15use rustc_span::Symbol;
16use tracing::{debug, warn};
17
18use super::data::*;
19use super::fs::*;
20use super::{file_format, work_product};
21use crate::errors;
22use crate::persist::file_format::{OpenFile, OpenFileError};
23
24#[derive(#[automatically_derived]
impl ::core::fmt::Debug for LoadResult {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
LoadResult::Ok {
prev_graph: __self_0, prev_work_products: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "Ok",
"prev_graph", __self_0, "prev_work_products", &__self_1),
LoadResult::DataOutOfDate =>
::core::fmt::Formatter::write_str(f, "DataOutOfDate"),
LoadResult::IoError { path: __self_0, err: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"IoError", "path", __self_0, "err", &__self_1),
}
}
}Debug)]
25enum LoadResult {
27 Ok { prev_graph: Arc<SerializedDepGraph>, prev_work_products: WorkProductMap },
29 DataOutOfDate,
31 IoError { path: PathBuf, err: io::Error },
33}
34
35fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) {
36 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_incremental/src/persist/load.rs:36",
"rustc_incremental::persist::load", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_incremental/src/persist/load.rs"),
::tracing_core::__macro_support::Option::Some(36u32),
::tracing_core::__macro_support::Option::Some("rustc_incremental::persist::load"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("delete_dirty_work_product({0:?})",
swp) as &dyn Value))])
});
} else { ; }
};debug!("delete_dirty_work_product({:?})", swp);
37 work_product::delete_workproduct_files(sess, &swp.work_product);
38}
39
40fn load_dep_graph(sess: &Session) -> LoadResult {
41 if !sess.opts.incremental.is_some() {
::core::panicking::panic("assertion failed: sess.opts.incremental.is_some()")
};assert!(sess.opts.incremental.is_some());
42
43 let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
44
45 let path = dep_graph_path(sess);
48 let expected_hash = sess.opts.dep_tracking_hash(false);
49
50 let mut prev_work_products = UnordMap::default();
51
52 if sess.incr_comp_session_dir_opt().is_some() {
56 let work_products_path = work_products_path(sess);
57
58 if let Ok(OpenFile { mmap, start_pos }) =
59 file_format::open_incremental_file(sess, &work_products_path)
60 {
61 let Ok(mut work_product_decoder) = MemDecoder::new(&mmap[..], start_pos) else {
63 sess.dcx().emit_warn(errors::CorruptFile { path: &work_products_path });
64 return LoadResult::DataOutOfDate;
65 };
66 let work_products: Vec<SerializedWorkProduct> =
67 Decodable::decode(&mut work_product_decoder);
68
69 for swp in work_products {
70 let all_files_exist = swp.work_product.saved_files.items().all(|(_, path)| {
71 let exists = in_incr_comp_dir_sess(sess, path).exists();
72 if !exists && sess.opts.unstable_opts.incremental_info {
73 {
::std::io::_eprint(format_args!("incremental: could not find file for work product: {0}\n",
path));
};eprintln!("incremental: could not find file for work product: {path}",);
74 }
75 exists
76 });
77
78 if all_files_exist {
79 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_incremental/src/persist/load.rs:79",
"rustc_incremental::persist::load", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_incremental/src/persist/load.rs"),
::tracing_core::__macro_support::Option::Some(79u32),
::tracing_core::__macro_support::Option::Some("rustc_incremental::persist::load"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("reconcile_work_products: all files for {0:?} exist",
swp) as &dyn Value))])
});
} else { ; }
};debug!("reconcile_work_products: all files for {:?} exist", swp);
80 prev_work_products.insert(swp.id, swp.work_product);
81 } else {
82 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_incremental/src/persist/load.rs:82",
"rustc_incremental::persist::load", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_incremental/src/persist/load.rs"),
::tracing_core::__macro_support::Option::Some(82u32),
::tracing_core::__macro_support::Option::Some("rustc_incremental::persist::load"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("reconcile_work_products: some file for {0:?} does not exist",
swp) as &dyn Value))])
});
} else { ; }
};debug!("reconcile_work_products: some file for {:?} does not exist", swp);
83 delete_dirty_work_product(sess, swp);
84 }
85 }
86 }
87 }
88
89 let _prof_timer = sess.prof.generic_activity("incr_comp_load_dep_graph");
90
91 match file_format::open_incremental_file(sess, &path) {
92 Err(OpenFileError::NotFoundOrHeaderMismatch) => LoadResult::DataOutOfDate,
93 Err(OpenFileError::IoError { err }) => LoadResult::IoError { path: path.to_owned(), err },
94 Ok(OpenFile { mmap, start_pos }) => {
95 let Ok(mut decoder) = MemDecoder::new(&mmap, start_pos) else {
96 sess.dcx().emit_warn(errors::CorruptFile { path: &path });
97 return LoadResult::DataOutOfDate;
98 };
99 let prev_commandline_args_hash = Hash64::decode(&mut decoder);
100
101 if prev_commandline_args_hash != expected_hash {
102 if sess.opts.unstable_opts.incremental_info {
103 {
::std::io::_eprint(format_args!("[incremental] completely ignoring cache because of differing commandline arguments\n"));
};eprintln!(
104 "[incremental] completely ignoring cache because of \
105 differing commandline arguments"
106 );
107 }
108 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_incremental/src/persist/load.rs:109",
"rustc_incremental::persist::load", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_incremental/src/persist/load.rs"),
::tracing_core::__macro_support::Option::Some(109u32),
::tracing_core::__macro_support::Option::Some("rustc_incremental::persist::load"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("load_dep_graph_new: differing commandline arg hashes")
as &dyn Value))])
});
} else { ; }
};debug!("load_dep_graph_new: differing commandline arg hashes");
110
111 return LoadResult::DataOutOfDate;
113 }
114
115 let prev_graph = SerializedDepGraph::decode(&mut decoder);
116
117 LoadResult::Ok { prev_graph, prev_work_products }
118 }
119 }
120}
121
122pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache> {
128 if sess.opts.incremental.is_none() {
129 return None;
130 }
131
132 let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
133
134 let path = query_cache_path(sess);
135 match file_format::open_incremental_file(sess, &path) {
136 Ok(OpenFile { mmap, start_pos }) => {
137 let cache = OnDiskCache::new(sess, mmap, start_pos).unwrap_or_else(|()| {
138 sess.dcx().emit_warn(errors::CorruptFile { path: &path });
139 OnDiskCache::new_empty()
140 });
141 Some(cache)
142 }
143 Err(OpenFileError::NotFoundOrHeaderMismatch | OpenFileError::IoError { .. }) => {
144 Some(OnDiskCache::new_empty())
145 }
146 }
147}
148
149fn maybe_assert_incr_state(sess: &Session, load_result: &LoadResult) {
152 let Some(assertion) = sess.opts.unstable_opts.assert_incr_state else { return };
154
155 let loaded = match load_result {
157 LoadResult::Ok { .. } => true,
158 LoadResult::DataOutOfDate | LoadResult::IoError { .. } => false,
159 };
160
161 match assertion {
162 IncrementalStateAssertion::Loaded => {
163 if !loaded {
164 sess.dcx().emit_fatal(errors::AssertLoaded);
165 }
166 }
167 IncrementalStateAssertion::NotLoaded => {
168 if loaded {
169 sess.dcx().emit_fatal(errors::AssertNotLoaded)
170 }
171 }
172 }
173}
174
175pub fn setup_dep_graph(
181 sess: &Session,
182 crate_name: Symbol,
183 stable_crate_id: StableCrateId,
184) -> DepGraph {
185 if sess.opts.incremental.is_none() {
186 return DepGraph::new_disabled();
187 }
188
189 prepare_session_directory(sess, crate_name, stable_crate_id);
191 let load_result = load_dep_graph(sess);
193
194 sess.time("incr_comp_garbage_collect_session_directories", || {
195 if let Err(e) = garbage_collect_session_directories(sess) {
196 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_incremental/src/persist/load.rs:196",
"rustc_incremental::persist::load", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_incremental/src/persist/load.rs"),
::tracing_core::__macro_support::Option::Some(196u32),
::tracing_core::__macro_support::Option::Some("rustc_incremental::persist::load"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("Error while trying to garbage collect incremental compilation cache directory: {0}",
e) as &dyn Value))])
});
} else { ; }
};warn!(
197 "Error while trying to garbage collect incremental compilation \
198 cache directory: {e}",
199 );
200 }
201 });
202
203 maybe_assert_incr_state(sess, &load_result);
205
206 let (prev_graph, prev_work_products) = match load_result {
207 LoadResult::IoError { path, err } => {
208 sess.dcx().emit_warn(errors::LoadDepGraph { path, err });
209 Default::default()
210 }
211 LoadResult::DataOutOfDate => {
212 if let Err(err) = delete_all_session_dir_contents(sess) {
213 sess.dcx().emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err });
214 }
215 Default::default()
216 }
217 LoadResult::Ok { prev_graph, prev_work_products } => (prev_graph, prev_work_products),
218 };
219
220 let path_buf = staging_dep_graph_path(sess);
222
223 let mut encoder = FileEncoder::new(&path_buf).unwrap_or_else(|err| {
224 sess.dcx().emit_fatal(errors::CreateDepGraph { path: &path_buf, err })
227 });
228
229 file_format::write_file_header(&mut encoder, sess);
230
231 sess.opts.dep_tracking_hash(false).encode(&mut encoder);
233
234 DepGraph::new(sess, prev_graph, prev_work_products, encoder)
235}