incr.comp.: Make #[rustc_dirty/clean] test for fingerprint equality instead of DepNode existence.
This commit is contained in:
parent
2a50d127dd
commit
45a03f153f
6 changed files with 33 additions and 88 deletions
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
¤t_metadata_hashes);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,6 @@ mod y {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue