Skip to content

Commit

Permalink
incr.comp.: Remove on-export crate metadata hashing.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelwoerister committed Nov 29, 2017
1 parent dc0e227 commit c60b0e4
Show file tree
Hide file tree
Showing 16 changed files with 39 additions and 603 deletions.
6 changes: 0 additions & 6 deletions src/librustc/ich/mod.rs
Expand Up @@ -28,8 +28,6 @@ mod impls_syntax;

pub const ATTR_DIRTY: &'static str = "rustc_dirty";
pub const ATTR_CLEAN: &'static str = "rustc_clean";
pub const ATTR_DIRTY_METADATA: &'static str = "rustc_metadata_dirty";
pub const ATTR_CLEAN_METADATA: &'static str = "rustc_metadata_clean";
pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
pub const ATTR_PARTITION_REUSED: &'static str = "rustc_partition_reused";
Expand All @@ -41,8 +39,6 @@ pub const DEP_GRAPH_ASSERT_ATTRS: &'static [&'static str] = &[
ATTR_THEN_THIS_WOULD_NEED,
ATTR_DIRTY,
ATTR_CLEAN,
ATTR_DIRTY_METADATA,
ATTR_CLEAN_METADATA,
ATTR_PARTITION_REUSED,
ATTR_PARTITION_TRANSLATED,
];
Expand All @@ -53,8 +49,6 @@ pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
ATTR_THEN_THIS_WOULD_NEED,
ATTR_DIRTY,
ATTR_CLEAN,
ATTR_DIRTY_METADATA,
ATTR_CLEAN_METADATA,
ATTR_PARTITION_REUSED,
ATTR_PARTITION_TRANSLATED,
];
30 changes: 2 additions & 28 deletions src/librustc/middle/cstore.rs
Expand Up @@ -175,32 +175,6 @@ impl EncodedMetadata {
}
}

/// The hash for some metadata that (when saving) will be exported
/// from this crate, or which (when importing) was exported by an
/// upstream crate.
#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
pub struct EncodedMetadataHash {
pub def_index: u32,
pub hash: ich::Fingerprint,
}

/// The hash for some metadata that (when saving) will be exported
/// from this crate, or which (when importing) was exported by an
/// upstream crate.
#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
pub struct EncodedMetadataHashes {
// Stable content hashes for things in crate metadata, indexed by DefIndex.
pub hashes: Vec<EncodedMetadataHash>,
}

impl EncodedMetadataHashes {
pub fn new() -> EncodedMetadataHashes {
EncodedMetadataHashes {
hashes: Vec::new(),
}
}
}

/// The backend's way to give the crate store access to the metadata in a library.
/// Note that it returns the raw metadata bytes stored in the library file, whether
/// it is compressed, uncompressed, some weird mix, etc.
Expand Down Expand Up @@ -286,7 +260,7 @@ pub trait CrateStore {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet)
-> (EncodedMetadata, EncodedMetadataHashes);
-> EncodedMetadata;
fn metadata_encoding_version(&self) -> &[u8];
}

Expand Down Expand Up @@ -370,7 +344,7 @@ impl CrateStore for DummyCrateStore {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet)
-> (EncodedMetadata, EncodedMetadataHashes) {
-> EncodedMetadata {
bug!("encode_metadata")
}
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/session/config.rs
Expand Up @@ -1072,8 +1072,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"attempt to recover from parse errors (experimental)"),
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
"enable incremental compilation (experimental)"),
incremental_cc: bool = (false, parse_bool, [UNTRACKED],
"enable cross-crate incremental compilation (even more experimental)"),
incremental_queries: bool = (true, parse_bool, [UNTRACKED],
"enable incremental compilation support for queries (experimental)"),
incremental_info: bool = (false, parse_bool, [UNTRACKED],
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/context.rs
Expand Up @@ -24,7 +24,7 @@ use hir::map::DefPathHash;
use lint::{self, Lint};
use ich::{StableHashingContext, NodeIdHashingMode};
use middle::const_val::ConstVal;
use middle::cstore::{CrateStore, LinkMeta, EncodedMetadataHashes};
use middle::cstore::{CrateStore, LinkMeta};
use middle::cstore::EncodedMetadata;
use middle::free_region::FreeRegionMap;
use middle::lang_items;
Expand Down Expand Up @@ -1246,7 +1246,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
pub fn encode_metadata(self, link_meta: &LinkMeta, reachable: &NodeSet)
-> (EncodedMetadata, EncodedMetadataHashes)
-> EncodedMetadata
{
self.cstore.encode_metadata(self, link_meta, reachable)
}
Expand Down
39 changes: 0 additions & 39 deletions src/librustc_incremental/persist/data.rs
Expand Up @@ -11,9 +11,6 @@
//! The data that we will serialize and deserialize.

use rustc::dep_graph::{WorkProduct, WorkProductId};
use rustc::hir::map::DefPathHash;
use rustc::middle::cstore::EncodedMetadataHash;
use rustc_data_structures::fx::FxHashMap;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SerializedWorkProduct {
Expand All @@ -23,39 +20,3 @@ pub struct SerializedWorkProduct {
/// work-product data itself
pub work_product: WorkProduct,
}

/// Data for use when downstream crates get recompiled.
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SerializedMetadataHashes {
/// For each def-id defined in this crate that appears in the
/// metadata, we hash all the inputs that were used when producing
/// the metadata. We save this after compilation is done. Then,
/// when some downstream crate is being recompiled, it can compare
/// the hashes we saved against the hashes that it saw from
/// before; this will tell it which of the items in this crate
/// changed, which in turn implies what items in the downstream
/// crate need to be recompiled.
///
/// Note that we store the def-ids here. This is because we don't
/// reload this file when we recompile this crate, we will just
/// regenerate it completely with the current hashes and new def-ids.
///
/// Then downstream creates will load up their
/// `SerializedDepGraph`, which may contain `MetaData(X)` nodes
/// where `X` refers to some item in this crate. That `X` will be
/// a `DefPathIndex` that gets retracted to the current `DefId`
/// (matching the one found in this structure).
pub entry_hashes: Vec<EncodedMetadataHash>,

/// For each DefIndex (as it occurs in SerializedMetadataHash), this
/// map stores the DefPathIndex (as it occurs in DefIdDirectory), so
/// that we can find the new DefId for a SerializedMetadataHash in a
/// subsequent compilation session.
///
/// This map is only needed for running auto-tests using the
/// #[rustc_metadata_dirty] and #[rustc_metadata_clean] attributes, and
/// is only populated if -Z query-dep-graph is specified. It will be
/// empty otherwise. Importing crates are perfectly happy with just having
/// the DefIndex.
pub index_map: FxHashMap<u32, DefPathHash>
}
172 changes: 2 additions & 170 deletions src/librustc_incremental/persist/dirty_clean.rs
Expand Up @@ -23,21 +23,6 @@
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
//!
//! The `#[rustc_metadata_dirty]` and `#[rustc_metadata_clean]` attributes
//! can be used to check the incremental compilation hash (ICH) values of
//! metadata exported in rlibs.
//!
//! - If a node is marked with `#[rustc_metadata_clean(cfg="rev2")]` we
//! check that the metadata hash for that node is the same for "rev2"
//! it was for "rev1".
//! - If a node is marked with `#[rustc_metadata_dirty(cfg="rev2")]` we
//! check that the metadata hash for that node is *different* for "rev2"
//! than it was for "rev1".
//!
//! Note that the metadata-testing attributes must never specify the
//! first revision. This would lead to a crash since there is no
//! previous revision to compare things to.
//!

use std::collections::HashSet;
use std::iter::FromIterator;
Expand All @@ -49,10 +34,9 @@ use rustc::hir::map::Node as HirNode;
use rustc::hir::def_id::DefId;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::intravisit;
use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA,
ATTR_CLEAN_METADATA};
use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN};
use syntax::ast::{self, Attribute, NestedMetaItem};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_data_structures::fx::FxHashSet;
use syntax_pos::Span;
use rustc::ty::TyCtxt;

Expand Down Expand Up @@ -553,157 +537,6 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
}
}

pub fn check_dirty_clean_metadata<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
prev_metadata_hashes: &FxHashMap<DefId, Fingerprint>,
current_metadata_hashes: &FxHashMap<DefId, Fingerprint>)
{
if !tcx.sess.opts.debugging_opts.query_dep_graph {
return;
}

tcx.dep_graph.with_ignore(||{
let krate = tcx.hir.krate();
let mut dirty_clean_visitor = DirtyCleanMetadataVisitor {
tcx,
prev_metadata_hashes,
current_metadata_hashes,
checked_attrs: FxHashSet(),
};
intravisit::walk_crate(&mut dirty_clean_visitor, krate);

let mut all_attrs = FindAllAttrs {
tcx,
attr_names: vec![ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA],
found_attrs: vec![],
};
intravisit::walk_crate(&mut all_attrs, krate);

// Note that we cannot use the existing "unused attribute"-infrastructure
// here, since that is running before trans. This is also the reason why
// all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs);
});
}

pub struct DirtyCleanMetadataVisitor<'a, 'tcx: 'a, 'm> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
prev_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
current_metadata_hashes: &'m FxHashMap<DefId, Fingerprint>,
checked_attrs: FxHashSet<ast::AttrId>,
}

impl<'a, 'tcx, 'm> intravisit::Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {

fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
intravisit::NestedVisitorMap::All(&self.tcx.hir)
}

fn visit_item(&mut self, item: &'tcx hir::Item) {
self.check_item(item.id, item.span);
intravisit::walk_item(self, item);
}

fn visit_variant(&mut self,
variant: &'tcx hir::Variant,
generics: &'tcx hir::Generics,
parent_id: ast::NodeId) {
if let Some(e) = variant.node.disr_expr {
self.check_item(e.node_id, variant.span);
}

intravisit::walk_variant(self, variant, generics, parent_id);
}

fn visit_variant_data(&mut self,
variant_data: &'tcx hir::VariantData,
_: ast::Name,
_: &'tcx hir::Generics,
_parent_id: ast::NodeId,
span: Span) {
if self.tcx.hir.find(variant_data.id()).is_some() {
// VariantData that represent structs or tuples don't have a
// separate entry in the HIR map and checking them would error,
// so only check if this is an enum or union variant.
self.check_item(variant_data.id(), span);
}

intravisit::walk_struct_def(self, variant_data);
}

fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
self.check_item(item.id, item.span);
intravisit::walk_trait_item(self, item);
}

fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
self.check_item(item.id, item.span);
intravisit::walk_impl_item(self, item);
}

fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) {
self.check_item(i.id, i.span);
intravisit::walk_foreign_item(self, i);
}

fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
self.check_item(s.id, s.span);
intravisit::walk_struct_field(self, s);
}
}

impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {

fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
let def_id = self.tcx.hir.local_def_id(item_id);

for attr in self.tcx.get_attrs(def_id).iter() {
if attr.check_name(ATTR_DIRTY_METADATA) {
if check_config(self.tcx, attr) {
if self.checked_attrs.insert(attr.id) {
self.assert_state(false, def_id, item_span);
}
}
} else if attr.check_name(ATTR_CLEAN_METADATA) {
if check_config(self.tcx, attr) {
if self.checked_attrs.insert(attr.id) {
self.assert_state(true, def_id, item_span);
}
}
}
}
}

fn assert_state(&self, should_be_clean: bool, def_id: DefId, span: Span) {
let item_path = self.tcx.item_path_str(def_id);
debug!("assert_state({})", item_path);

if let Some(&prev_hash) = self.prev_metadata_hashes.get(&def_id) {
let hashes_are_equal = prev_hash == self.current_metadata_hashes[&def_id];

if should_be_clean && !hashes_are_equal {
self.tcx.sess.span_err(
span,
&format!("Metadata hash of `{}` is dirty, but should be clean",
item_path));
}

let should_be_dirty = !should_be_clean;
if should_be_dirty && hashes_are_equal {
self.tcx.sess.span_err(
span,
&format!("Metadata hash of `{}` is clean, but should be dirty",
item_path));
}
} else {
self.tcx.sess.span_err(
span,
&format!("Could not find previous metadata hash of `{}`",
item_path));
}
}
}

/// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
/// for a `cfg="foo"` attribute and check whether we have a cfg
/// flag called `foo`.
Expand Down Expand Up @@ -759,7 +592,6 @@ fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name {
}
}


// A visitor that collects all #[rustc_dirty]/#[rustc_clean] attributes from
// the HIR. It is used to verfiy that we really ran checks for all annotated
// nodes.
Expand Down
5 changes: 0 additions & 5 deletions src/librustc_incremental/persist/fs.rs
Expand Up @@ -131,7 +131,6 @@ use rand::{thread_rng, Rng};
const LOCK_FILE_EXT: &'static str = ".lock";
const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin";
const METADATA_HASHES_FILENAME: &'static str = "metadata.bin";
const QUERY_CACHE_FILENAME: &'static str = "query-cache.bin";

// We encode integers using the following base, so they are shorter than decimal
Expand All @@ -148,10 +147,6 @@ pub fn work_products_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)
}

pub fn metadata_hash_export_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, METADATA_HASHES_FILENAME)
}

pub fn query_cache_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME)
}
Expand Down

0 comments on commit c60b0e4

Please sign in to comment.