提交 45a03f15 编写于 作者: M Michael Woerister

incr.comp.: Make #[rustc_dirty/clean] test for fingerprint equality instead of DepNode existence.

上级 2a50d127
......@@ -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 @@
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 @@ fn dep_node_str(&self, dep_node: &DepNode) -> String {
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 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,
&current_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 @@ pub fn 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 @@ pub fn 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();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册