Skip to content

Commit

Permalink
incr.comp.: Make #[rustc_dirty/clean] test for fingerprint equality i…
Browse files Browse the repository at this point in the history
…nstead of DepNode existence.
  • Loading branch information
michaelwoerister committed Sep 23, 2017
1 parent 2a50d12 commit 45a03f1
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 88 deletions.
105 changes: 25 additions & 80 deletions src/librustc_incremental/persist/dirty_clean.rs
Expand Up @@ -8,18 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Debugging code to test the state of the dependency graph just
//! after it is loaded from disk and just after it has been saved.
//! Debugging code to test fingerprints computed for query results.
//! For each node marked with `#[rustc_clean]` or `#[rustc_dirty]`,
//! we will check that a suitable node for that item either appears
//! or does not appear in the dep-graph, as appropriate:
//! we will compare the fingerprint from the current and from the previous
//! compilation session as appropriate:
//!
//! - `#[rustc_dirty(label="TypeckTables", cfg="rev2")]` if we are
//! in `#[cfg(rev2)]`, then there MUST NOT be a node
//! `DepNode::TypeckTables(X)` where `X` is the def-id of the
//! current node.
//! in `#[cfg(rev2)]`, then the fingerprints associated with
//! `DepNode::TypeckTables(X)` must be DIFFERENT (`X` is the def-id of the
//! current node).
//! - `#[rustc_clean(label="TypeckTables", cfg="rev2")]` same as above,
//! except that the node MUST exist.
//! except that the fingerprints must be the SAME.
//!
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
Expand All @@ -40,9 +39,7 @@
//! previous revision to compare things to.
//!

use super::data::DepNodeIndex;
use super::load::DirtyNodes;
use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind};
use rustc::dep_graph::DepNode;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
Expand All @@ -51,41 +48,22 @@ use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA,
ATTR_CLEAN_METADATA};
use syntax::ast::{self, Attribute, NestedMetaItem};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_data_structures::indexed_vec::IndexVec;
use syntax_pos::Span;
use rustc::ty::TyCtxt;

const LABEL: &'static str = "label";
const CFG: &'static str = "cfg";

pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
nodes: &IndexVec<DepNodeIndex, DepNode>,
dirty_inputs: &DirtyNodes) {
pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
// can't add `#[rustc_dirty]` etc without opting in to this feature
if !tcx.sess.features.borrow().rustc_attrs {
return;
}

let _ignore = tcx.dep_graph.in_ignore();
let dirty_inputs: FxHashSet<DepNode> =
dirty_inputs.keys()
.filter_map(|dep_node_index| {
let dep_node = nodes[*dep_node_index];
if dep_node.extract_def_id(tcx).is_some() {
Some(dep_node)
} else {
None
}
})
.collect();

let query = tcx.dep_graph.query();
debug!("query-nodes: {:?}", query.nodes());
let krate = tcx.hir.krate();
let mut dirty_clean_visitor = DirtyCleanVisitor {
tcx,
query: &query,
dirty_inputs,
checked_attrs: FxHashSet(),
};
krate.visit_all_item_likes(&mut dirty_clean_visitor);
Expand All @@ -105,8 +83,6 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
query: &'a DepGraphQuery,
dirty_inputs: FxHashSet<DepNode>,
checked_attrs: FxHashSet<ast::AttrId>,
}

Expand Down Expand Up @@ -143,59 +119,28 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
debug!("assert_dirty({:?})", dep_node);

match dep_node.kind {
DepKind::Krate |
DepKind::Hir |
DepKind::HirBody => {
// HIR nodes are inputs, so if we are asserting that the HIR node is
// dirty, we check the dirty input set.
if !self.dirty_inputs.contains(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
item_span,
&format!("`{}` not found in dirty set, but should be dirty",
dep_node_str));
}
}
_ => {
// Other kinds of nodes would be targets, so check if
// the dep-graph contains the node.
if self.query.contains_node(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
item_span,
&format!("`{}` found in dep graph, but should be dirty", dep_node_str));
}
}
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);

if current_fingerprint == prev_fingerprint {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
item_span,
&format!("`{}` should be dirty but is not", dep_node_str));
}
}

fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
debug!("assert_clean({:?})", dep_node);

match dep_node.kind {
DepKind::Krate |
DepKind::Hir |
DepKind::HirBody => {
// For HIR nodes, check the inputs.
if self.dirty_inputs.contains(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
item_span,
&format!("`{}` found in dirty-node set, but should be clean",
dep_node_str));
}
}
_ => {
// Otherwise, check if the dep-node exists.
if !self.query.contains_node(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
item_span,
&format!("`{}` not found in dep graph, but should be clean",
dep_node_str));
}
}
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);

if current_fingerprint != prev_fingerprint {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx.sess.span_err(
item_span,
&format!("`{}` should be clean but is not", dep_node_str));
}
}

Expand Down
4 changes: 0 additions & 4 deletions src/librustc_incremental/persist/load.rs
Expand Up @@ -23,7 +23,6 @@ use rustc_serialize::opaque::Decoder;
use std::path::{Path};

use super::data::*;
use super::dirty_clean;
use super::fs::*;
use super::file_format;
use super::work_product;
Expand Down Expand Up @@ -186,9 +185,6 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// dirty.
reconcile_work_products(tcx, work_products, &clean_work_products);

dirty_clean::check_dirty_clean_annotations(tcx,
&serialized_dep_graph.nodes,
&dirty_raw_nodes);
Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc_incremental/persist/save.rs
Expand Up @@ -89,6 +89,7 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|e| encode_dep_graph_new(tcx, e));
});

dirty_clean::check_dirty_clean_annotations(tcx);
dirty_clean::check_dirty_clean_metadata(tcx,
&prev_metadata_hashes,
&current_metadata_hashes);
Expand Down
4 changes: 2 additions & 2 deletions src/test/incremental/dirty_clean.rs
Expand Up @@ -37,14 +37,14 @@ mod y {

#[rustc_clean(label="TypeckTables", cfg="cfail2")]
pub fn y() {
//[cfail2]~^ ERROR `TypeckTables(y::y)` not found in dep graph, but should be clean
//[cfail2]~^ ERROR `TypeckTables(y::y)` should be clean but is not
x::x();
}
}

mod z {
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
pub fn z() {
//[cfail2]~^ ERROR `TypeckTables(z::z)` found in dep graph, but should be dirty
//[cfail2]~^ ERROR `TypeckTables(z::z)` should be dirty but is not
}
}
2 changes: 1 addition & 1 deletion src/test/incremental/hashes/enum_defs.rs
Expand Up @@ -143,7 +143,7 @@ enum EnumChangeValueCStyleVariant1 {
#[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_clean(label="HirBody", cfg="cfail2")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
Expand Down
5 changes: 4 additions & 1 deletion src/test/incremental/string_constant.rs
Expand Up @@ -27,7 +27,8 @@ mod x {
}

#[cfg(rpass2)]
#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
#[rustc_dirty(label="HirBody", cfg="rpass2")]
#[rustc_dirty(label="MirOptimized", cfg="rpass2")]
pub fn x() {
println!("{}", "2");
}
Expand All @@ -37,6 +38,7 @@ mod y {
use x;

#[rustc_clean(label="TypeckTables", cfg="rpass2")]
#[rustc_clean(label="MirOptimized", cfg="rpass2")]
pub fn y() {
x::x();
}
Expand All @@ -46,6 +48,7 @@ mod z {
use y;

#[rustc_clean(label="TypeckTables", cfg="rpass2")]
#[rustc_clean(label="MirOptimized", cfg="rpass2")]
pub fn z() {
y::y();
}
Expand Down

0 comments on commit 45a03f1

Please sign in to comment.