diff options
Diffstat (limited to 'compiler/rustc_incremental/src')
| -rw-r--r-- | compiler/rustc_incremental/src/assert_dep_graph.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/assert_module_sources.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/dirty_clean.rs | 61 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/file_format.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/fs.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/fs/tests.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/load.rs | 58 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/save.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/work_product.rs | 6 |
10 files changed, 156 insertions, 60 deletions
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 571337a8dcb..60b48e9bc8a 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -39,11 +39,11 @@ use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMIN use rustc_graphviz as dot; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::dep_graph::{ DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, }; -use rustc_middle::hir::map::Map; +use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -52,6 +52,7 @@ use std::env; use std::fs::{self, File}; use std::io::{BufWriter, Write}; +#[allow(missing_docs)] pub fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.debugging_opts.dump_dep_graph { @@ -102,7 +103,7 @@ struct IfThisChanged<'tcx> { then_this_would_need: Targets, } -impl IfThisChanged<'tcx> { +impl<'tcx> IfThisChanged<'tcx> { fn argument(&self, attr: &ast::Attribute) -> Option<Symbol> { let mut value = None; for list_item in attr.meta_item_list().unwrap_or_default() { @@ -130,7 +131,7 @@ impl IfThisChanged<'tcx> { DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner) } Some(n) => { - match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -146,7 +147,7 @@ impl IfThisChanged<'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { - match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -171,11 +172,11 @@ impl IfThisChanged<'tcx> { } } -impl Visitor<'tcx> for IfThisChanged<'tcx> { - type Map = Map<'tcx>; +impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> { + type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::OnlyBodies(self.tcx.hir()) + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -262,6 +263,7 @@ fn dump_graph(query: &DepGraphQuery) { } } +#[allow(missing_docs)] pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, Vec<(&'q DepNode, &'q DepNode)>); impl<'a, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index a5f3e4553ce..4b235213f7f 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -29,6 +29,7 @@ use rustc_session::cgu_reuse_tracker::*; use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeSet; +#[allow(missing_docs)] pub fn assert_module_sources(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.incremental.is_none() { @@ -55,7 +56,7 @@ struct AssertModuleSource<'tcx> { available_cgus: BTreeSet<String>, } -impl AssertModuleSource<'tcx> { +impl<'tcx> AssertModuleSource<'tcx> { fn check_attr(&self, attr: &ast::Attribute) { let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) { (CguReuse::PreLto, ComparisonKind::AtLeast) @@ -123,7 +124,7 @@ impl AssertModuleSource<'tcx> { debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name); - if !self.available_cgus.contains(&*cgu_name.as_str()) { + if !self.available_cgus.contains(cgu_name.as_str()) { self.tcx.sess.span_err( attr.span, &format!( diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index dd3f8c937f8..df64534ce54 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -1,7 +1,7 @@ //! Support for serializing the dep-graph and reloading it. +#![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index b2eaf61b7d1..94c149dd23e 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -9,6 +9,13 @@ //! - `#[rustc_clean(cfg="rev2")]` same as above, except that the //! fingerprints must be the SAME (along with all other fingerprints). //! +//! - `#[rustc_clean(cfg="rev2", loaded_from_disk='typeck")]` asserts that +//! the query result for `DepNode::typeck(X)` was actually +//! loaded from disk (not just marked green). This can be useful +//! to ensure that a test is actually exercising the deserialization +//! logic for a particular query result. This can be combined with +//! `except` +//! //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. @@ -21,13 +28,14 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::Node as HirNode; use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind}; use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt}; -use rustc_middle::hir::map::Map; +use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use std::iter::FromIterator; use std::vec::Vec; +const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; const EXCEPT: Symbol = sym::except; const CFG: Symbol = sym::cfg; @@ -124,6 +132,7 @@ type Labels = FxHashSet<String>; struct Assertion { clean: Labels, dirty: Labels, + loaded_from_disk: Labels, } pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { @@ -155,7 +164,7 @@ pub struct DirtyCleanVisitor<'tcx> { checked_attrs: FxHashSet<ast::AttrId>, } -impl DirtyCleanVisitor<'tcx> { +impl<'tcx> DirtyCleanVisitor<'tcx> { /// Possibly "deserialize" the attribute into a clean/dirty assertion fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option<Assertion> { if !attr.has_name(sym::rustc_clean) { @@ -174,6 +183,7 @@ impl DirtyCleanVisitor<'tcx> { fn assertion_auto(&mut self, item_id: LocalDefId, attr: &Attribute) -> Assertion { let (name, mut auto) = self.auto_labels(item_id, attr); let except = self.except(attr); + let loaded_from_disk = self.loaded_from_disk(attr); for e in except.iter() { if !auto.remove(e) { let msg = format!( @@ -183,7 +193,19 @@ impl DirtyCleanVisitor<'tcx> { self.tcx.sess.span_fatal(attr.span, &msg); } } - Assertion { clean: auto, dirty: except } + Assertion { clean: auto, dirty: except, loaded_from_disk } + } + + /// `loaded_from_disk=` attribute value + fn loaded_from_disk(&self, attr: &Attribute) -> Labels { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { + if item.has_name(LOADED_FROM_DISK) { + let value = expect_associated_value(self.tcx, &item); + return self.resolve_labels(&item, value); + } + } + // If `loaded_from_disk=` is not specified, don't assert anything + Labels::default() } /// `except=` attribute value @@ -201,8 +223,7 @@ impl DirtyCleanVisitor<'tcx> { /// Return all DepNode labels that should be asserted for this item. /// index=0 is the "name" used for error messages fn auto_labels(&mut self, item_id: LocalDefId, attr: &Attribute) -> (&'static str, Labels) { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(item_id); - let node = self.tcx.hir().get(hir_id); + let node = self.tcx.hir().get_by_def_id(item_id); let (name, labels) = match node { HirNode::Item(item) => { match item.kind { @@ -332,6 +353,18 @@ impl DirtyCleanVisitor<'tcx> { } } + fn assert_loaded_from_disk(&self, item_span: Span, dep_node: DepNode) { + debug!("assert_loaded_from_disk({:?})", dep_node); + + if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) { + let dep_node_str = self.dep_node_str(&dep_node); + self.tcx.sess.span_err( + item_span, + &format!("`{}` should have been loaded from disk but it was not", dep_node_str), + ); + } + } + fn check_item(&mut self, item_id: LocalDefId, item_span: Span) { let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() { @@ -348,11 +381,15 @@ impl DirtyCleanVisitor<'tcx> { let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); self.assert_dirty(item_span, dep_node); } + for label in assertion.loaded_from_disk { + let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); + self.assert_loaded_from_disk(item_span, dep_node); + } } } } -impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.check_item(item.def_id, item.span); } @@ -382,7 +419,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { let value = expect_associated_value(tcx, &item); debug!("check_config: searching for cfg {:?}", value); cfg = Some(config.contains(&(value, None))); - } else if !item.has_name(EXCEPT) { + } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty())); } } @@ -415,7 +452,7 @@ pub struct FindAllAttrs<'tcx> { found_attrs: Vec<&'tcx Attribute>, } -impl FindAllAttrs<'tcx> { +impl<'tcx> FindAllAttrs<'tcx> { fn is_active_attr(&mut self, attr: &Attribute) -> bool { if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) { return true; @@ -434,11 +471,11 @@ impl FindAllAttrs<'tcx> { } } -impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { - type Map = Map<'tcx>; +impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { + type NestedFilter = nested_filter::All; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { - intravisit::NestedVisitorMap::All(self.tcx.hir()) + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() } fn visit_attribute(&mut self, _: hir::HirId, attr: &'tcx Attribute) { diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 392c5bdc15a..68180a2214a 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -190,7 +190,7 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: & fn rustc_version(nightly_build: bool) -> String { if nightly_build { - if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") { return val.to_string_lossy().into_owned(); } } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 38cbf5314ef..a49a1554d5b 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -133,24 +133,26 @@ const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; // case-sensitive (as opposed to base64, for example). const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE; +/// Returns the path to a session's dependency graph. pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } +/// Returns the path to a session's staging dependency graph. +/// +/// On the difference between dep-graph and staging dep-graph, +/// see `build_dep_graph`. pub fn staging_dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME) } -pub fn dep_graph_path_from(incr_comp_session_dir: &Path) -> PathBuf { - in_incr_comp_dir(incr_comp_session_dir, DEP_GRAPH_FILENAME) -} - pub fn work_products_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME) } - +/// Returns the path to a session's query cache. pub fn query_cache_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME) } +/// Locks a given session directory. pub fn lock_file_path(session_dir: &Path) -> PathBuf { let crate_dir = session_dir.parent().unwrap(); @@ -169,23 +171,35 @@ pub fn lock_file_path(session_dir: &Path) -> PathBuf { crate_dir.join(&directory_name[0..dash_indices[2]]).with_extension(&LOCK_FILE_EXT[1..]) } +/// Returns the path for a given filename within the incremental compilation directory +/// in the current session. pub fn in_incr_comp_dir_sess(sess: &Session, file_name: &str) -> PathBuf { in_incr_comp_dir(&sess.incr_comp_session_dir(), file_name) } +/// Returns the path for a given filename within the incremental compilation directory, +/// not necessarily from the current session. +/// +/// To ensure the file is part of the current session, use [`in_incr_comp_dir_sess`]. pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBuf { incr_comp_session_dir.join(file_name) } -/// Allocates the private session directory. The boolean in the Ok() result -/// indicates whether we should try loading a dep graph from the successfully -/// initialized directory, or not. -/// The post-condition of this fn is that we have a valid incremental -/// compilation session directory, if the result is `Ok`. A valid session +/// Allocates the private session directory. +/// +/// If the result of this function is `Ok`, we have a valid incremental +/// compilation session directory. A valid session /// directory is one that contains a locked lock file. It may or may not contain /// a dep-graph and work products from a previous session. -/// If the call fails, the fn may leave behind an invalid session directory. +/// +/// This always attempts to load a dep-graph from the directory. +/// If loading fails for some reason, we fallback to a disabled `DepGraph`. +/// See [`rustc_interface::queries::dep_graph`]. +/// +/// If this function returns an error, it may leave behind an invalid session directory. /// The garbage collection will take care of it. +/// +/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph pub fn prepare_session_directory( sess: &Session, crate_name: &str, @@ -664,6 +678,7 @@ fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool { timestamp < SystemTime::now() - Duration::from_secs(10) } +/// Runs garbage collection for the current session. pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { debug!("garbage_collect_session_directories() - begin"); diff --git a/compiler/rustc_incremental/src/persist/fs/tests.rs b/compiler/rustc_incremental/src/persist/fs/tests.rs index 652ef6bcdce..184796948b6 100644 --- a/compiler/rustc_incremental/src/persist/fs/tests.rs +++ b/compiler/rustc_incremental/src/persist/fs/tests.rs @@ -13,7 +13,7 @@ fn test_all_except_most_recent() { .keys() .cloned() .collect::<FxHashSet<PathBuf>>(), - vec![PathBuf::from("1"), PathBuf::from("2"), PathBuf::from("3"), PathBuf::from("4"),] + [PathBuf::from("1"), PathBuf::from("2"), PathBuf::from("3"), PathBuf::from("4"),] .into_iter() .collect::<FxHashSet<PathBuf>>() ); @@ -40,7 +40,7 @@ fn test_find_source_directory_in_iter() { // Find newest assert_eq!( find_source_directory_in_iter( - vec![ + [ PathBuf::from("crate-dir/s-3234-0000-svh"), PathBuf::from("crate-dir/s-2234-0000-svh"), PathBuf::from("crate-dir/s-1234-0000-svh") @@ -54,7 +54,7 @@ fn test_find_source_directory_in_iter() { // Filter out "-working" assert_eq!( find_source_directory_in_iter( - vec![ + [ PathBuf::from("crate-dir/s-3234-0000-working"), PathBuf::from("crate-dir/s-2234-0000-svh"), PathBuf::from("crate-dir/s-1234-0000-svh") @@ -66,12 +66,12 @@ fn test_find_source_directory_in_iter() { ); // Handle empty - assert_eq!(find_source_directory_in_iter(vec![].into_iter(), &already_visited), None); + assert_eq!(find_source_directory_in_iter([].into_iter(), &already_visited), None); // Handle only working assert_eq!( find_source_directory_in_iter( - vec![ + [ PathBuf::from("crate-dir/s-3234-0000-working"), PathBuf::from("crate-dir/s-2234-0000-working"), PathBuf::from("crate-dir/s-1234-0000-working") diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 4d38556e5d2..870c3f80682 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -6,6 +6,7 @@ use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::OnDiskCache; use rustc_serialize::opaque::Decoder; use rustc_serialize::Decodable; +use rustc_session::config::IncrementalStateAssertion; use rustc_session::Session; use std::path::Path; @@ -16,14 +17,46 @@ use super::work_product; type WorkProductMap = FxHashMap<WorkProductId, WorkProduct>; +#[derive(Debug)] +/// Represents the result of an attempt to load incremental compilation data. pub enum LoadResult<T> { - Ok { data: T }, + /// Loading was successful. + Ok { + #[allow(missing_docs)] + data: T, + }, + /// The file either didn't exist or was produced by an incompatible compiler version. DataOutOfDate, - Error { message: String }, + /// An error occured. + Error { + #[allow(missing_docs)] + message: String, + }, } impl<T: Default> LoadResult<T> { + /// Accesses the data returned in [`LoadResult::Ok`]. pub fn open(self, sess: &Session) -> T { + // Check for errors when using `-Zassert-incremental-state` + match (sess.opts.assert_incr_state, &self) { + (Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => { + sess.fatal( + "We asserted that the incremental cache should not be loaded, \ + but it was loaded.", + ); + } + ( + Some(IncrementalStateAssertion::Loaded), + LoadResult::Error { .. } | LoadResult::DataOutOfDate, + ) => { + sess.fatal( + "We asserted that an existing incremental cache directory should \ + be successfully loaded, but it was not.", + ); + } + _ => {} + }; + match self { LoadResult::Error { message } => { sess.warn(&message); @@ -33,7 +66,7 @@ impl<T: Default> LoadResult<T> { if let Err(err) = delete_all_session_dir_contents(sess) { sess.err(&format!( "Failed to delete invalidated or incompatible \ - incremental compilation session directory contents `{}`: {}.", + incremental compilation session directory contents `{}`: {}.", dep_graph_path(sess).display(), err )); @@ -77,6 +110,7 @@ pub enum MaybeAsync<T> { } impl<T> MaybeAsync<LoadResult<T>> { + /// Accesses the data returned in [`LoadResult::Ok`] in an asynchronous way if possible. pub fn open(self) -> LoadResult<T> { match self { MaybeAsync::Sync(result) => result, @@ -87,6 +121,7 @@ impl<T> MaybeAsync<LoadResult<T>> { } } +/// An asynchronous type for computing the dependency graph. pub type DepGraphFuture = MaybeAsync<LoadResult<(SerializedDepGraph, WorkProductMap)>>; /// Launch a thread and load the dependency graph in the background. @@ -105,7 +140,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // 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 path = dep_graph_path_from(&sess.incr_comp_session_dir()); + let path = dep_graph_path(&sess); let report_incremental_info = sess.opts.debugging_opts.incremental_info; let expected_hash = sess.opts.dep_tracking_hash(false); @@ -123,14 +158,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // Decode the list of work_products let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos); let work_products: Vec<SerializedWorkProduct> = - Decodable::decode(&mut work_product_decoder).unwrap_or_else(|e| { - let msg = format!( - "Error decoding `work-products` from incremental \ - compilation session directory: {}", - e - ); - sess.fatal(&msg[..]) - }); + Decodable::decode(&mut work_product_decoder); for swp in work_products { let mut all_files_exist = true; @@ -168,8 +196,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { LoadResult::Error { message } => LoadResult::Error { message }, LoadResult::Ok { data: (bytes, start_pos) } => { let mut decoder = Decoder::new(&bytes, start_pos); - let prev_commandline_args_hash = u64::decode(&mut decoder) - .expect("Error reading commandline arg hash from cached dep-graph"); + let prev_commandline_args_hash = u64::decode(&mut decoder); if prev_commandline_args_hash != expected_hash { if report_incremental_info { @@ -185,8 +212,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { return LoadResult::DataOutOfDate; } - let dep_graph = SerializedDepGraph::decode(&mut decoder) - .expect("Error reading cached dep-graph"); + let dep_graph = SerializedDepGraph::decode(&mut decoder); LoadResult::Ok { data: (dep_graph, prev_work_products) } } diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 6c683058b12..9601a49267f 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -13,9 +13,13 @@ use super::file_format; use super::fs::*; use super::work_product; -/// Save and dump the DepGraph. +/// Saves and writes the [`DepGraph`] to the file system. /// -/// No query must be invoked after this function. +/// This function saves both the dep-graph and the query result cache, +/// and drops the result cache. +/// +/// This function should only run after all queries have completed. +/// Trying to execute a query afterwards would attempt to read the result cache we just dropped. pub fn save_dep_graph(tcx: TyCtxt<'_>) { debug!("save_dep_graph()"); tcx.dep_graph.with_ignore(|| { @@ -75,6 +79,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { }) } +/// Saves the work product index. pub fn save_work_product_index( sess: &Session, dep_graph: &DepGraph, @@ -139,6 +144,12 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeR tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder)) } +/// Builds the dependency graph. +/// +/// This function breates the *staging dep-graph*. When the dep-graph is modified by a query +/// execution, the new dependency information is not kept in memory but directly +/// output to this file. `save_dep_graph` then finalizes the staging dep-graph +/// and moves it to the permanent dep-graph path pub fn build_dep_graph( sess: &Session, prev_graph: SerializedDepGraph, diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 19d64bda56d..85b44ed7531 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -1,4 +1,6 @@ -//! This module contains files for saving intermediate work-products. +//! Functions for saving and removing intermediate [work products]. +//! +//! [work products]: WorkProduct use crate::persist::fs::*; use rustc_fs_util::link_or_copy; @@ -7,6 +9,7 @@ use rustc_session::Session; use std::fs as std_fs; use std::path::PathBuf; +/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it. pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, @@ -40,6 +43,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( Some((work_product_id, work_product)) } +/// Removes files for a given work product. pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { if let Some(ref file_name) = work_product.saved_file { let path = in_incr_comp_dir_sess(sess, file_name); |
