Skip to content

Commit 775bd93

Browse files
committed
make it possible to test if HIR is dirty
This requires passing in the dirty-node set explicitly since HIR nodes wind up added to the graph either way.
1 parent e1d2bc2 commit 775bd93

File tree

3 files changed

+68
-16
lines changed

3 files changed

+68
-16
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ impl<D: Clone + Debug> DepNode<D> {
150150
check! {
151151
CollectItem,
152152
BorrowCheck,
153+
Hir,
153154
TransCrateItem,
154155
TypeckItemType,
155156
TypeckItemBody,

src/librustc_incremental/persist/dirty_clean.rs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@
2424
//! Errors are reported if we are in the suitable configuration but
2525
//! the required condition is not met.
2626
27+
use super::directory::RetracedDefIdDirectory;
28+
use super::load::DirtyNodes;
2729
use rustc::dep_graph::{DepGraphQuery, DepNode};
2830
use rustc::hir;
2931
use rustc::hir::def_id::DefId;
3032
use rustc::hir::intravisit::Visitor;
33+
use rustc_data_structures::fnv::FnvHashSet;
3134
use syntax::ast::{self, Attribute, MetaItem};
3235
use syntax::attr::AttrMetaMethods;
3336
use syntax::parse::token::InternedString;
@@ -38,19 +41,33 @@ const CLEAN: &'static str = "rustc_clean";
3841
const LABEL: &'static str = "label";
3942
const CFG: &'static str = "cfg";
4043

41-
pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
44+
pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
45+
dirty_inputs: &DirtyNodes,
46+
retraced: &RetracedDefIdDirectory) {
47+
// can't add `#[rustc_dirty]` etc without opting in to this feature
48+
if !tcx.sess.features.borrow().rustc_attrs {
49+
return;
50+
}
51+
4252
let _ignore = tcx.dep_graph.in_ignore();
53+
let dirty_inputs: FnvHashSet<DepNode<DefId>> =
54+
dirty_inputs.iter()
55+
.filter_map(|d| retraced.map(d))
56+
.collect();
4357
let query = tcx.dep_graph.query();
58+
debug!("query-nodes: {:?}", query.nodes());
4459
let krate = tcx.map.krate();
4560
krate.visit_all_items(&mut DirtyCleanVisitor {
4661
tcx: tcx,
4762
query: &query,
63+
dirty_inputs: dirty_inputs,
4864
});
4965
}
5066

5167
pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
5268
tcx: TyCtxt<'a, 'tcx, 'tcx>,
5369
query: &'a DepGraphQuery<DefId>,
70+
dirty_inputs: FnvHashSet<DepNode<DefId>>,
5471
}
5572

5673
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
@@ -81,10 +98,13 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
8198
return true;
8299
}
83100
}
101+
return false;
84102
}
85103
}
86-
debug!("check_config: no match found");
87-
return false;
104+
105+
self.tcx.sess.span_fatal(
106+
attr.span,
107+
&format!("no cfg attribute"));
88108
}
89109

90110
fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
@@ -105,29 +125,59 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
105125
self.tcx.sess.span_fatal(attr.span, "no `label` found");
106126
}
107127

108-
fn dep_node_str(&self, dep_node: DepNode<DefId>) -> DepNode<String> {
128+
fn dep_node_str(&self, dep_node: &DepNode<DefId>) -> DepNode<String> {
109129
dep_node.map_def(|&def_id| Some(self.tcx.item_path_str(def_id))).unwrap()
110130
}
111131

112132
fn assert_dirty(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
113133
debug!("assert_dirty({:?})", dep_node);
114134

115-
if self.query.contains_node(&dep_node) {
116-
let dep_node_str = self.dep_node_str(dep_node);
117-
self.tcx.sess.span_err(
118-
item.span,
119-
&format!("`{:?}` found in dep graph, but should be dirty", dep_node_str));
135+
match dep_node {
136+
DepNode::Hir(_) => {
137+
// HIR nodes are inputs, so if we are asserting that the HIR node is
138+
// dirty, we check the dirty input set.
139+
if !self.dirty_inputs.contains(&dep_node) {
140+
let dep_node_str = self.dep_node_str(&dep_node);
141+
self.tcx.sess.span_err(
142+
item.span,
143+
&format!("`{:?}` not found in dirty set, but should be dirty", dep_node_str));
144+
}
145+
}
146+
_ => {
147+
// Other kinds of nodes would be targets, so check if
148+
// the dep-graph contains the node.
149+
if self.query.contains_node(&dep_node) {
150+
let dep_node_str = self.dep_node_str(&dep_node);
151+
self.tcx.sess.span_err(
152+
item.span,
153+
&format!("`{:?}` found in dep graph, but should be dirty", dep_node_str));
154+
}
155+
}
120156
}
121157
}
122158

123159
fn assert_clean(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
124160
debug!("assert_clean({:?})", dep_node);
125161

126-
if !self.query.contains_node(&dep_node) {
127-
let dep_node_str = self.dep_node_str(dep_node);
128-
self.tcx.sess.span_err(
129-
item.span,
130-
&format!("`{:?}` not found in dep graph, but should be clean", dep_node_str));
162+
match dep_node {
163+
DepNode::Hir(_) => {
164+
// For HIR nodes, check the inputs.
165+
if self.dirty_inputs.contains(&dep_node) {
166+
let dep_node_str = self.dep_node_str(&dep_node);
167+
self.tcx.sess.span_err(
168+
item.span,
169+
&format!("`{:?}` found in dirty-node set, but should be clean", dep_node_str));
170+
}
171+
}
172+
_ => {
173+
// Otherwise, check if the dep-node exists.
174+
if !self.query.contains_node(&dep_node) {
175+
let dep_node_str = self.dep_node_str(&dep_node);
176+
self.tcx.sess.span_err(
177+
item.span,
178+
&format!("`{:?}` not found in dep graph, but should be clean", dep_node_str));
179+
}
180+
}
131181
}
132182
}
133183
}

src/librustc_incremental/persist/load.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use super::dirty_clean;
2828
use super::hash::*;
2929
use super::util::*;
3030

31-
type DirtyNodes = FnvHashSet<DepNode<DefPathIndex>>;
31+
pub type DirtyNodes = FnvHashSet<DepNode<DefPathIndex>>;
3232

3333
type CleanEdges = Vec<(DepNode<DefId>, DepNode<DefId>)>;
3434

@@ -45,7 +45,6 @@ pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
4545

4646
let _ignore = tcx.dep_graph.in_ignore();
4747
load_dep_graph_if_exists(tcx);
48-
dirty_clean::check_dirty_clean_annotations(tcx);
4948
}
5049

5150
fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -184,6 +183,8 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
184183
let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
185184
reconcile_work_products(tcx, work_products, &dirty_target_nodes);
186185

186+
dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_source_nodes, &retraced);
187+
187188
Ok(())
188189
}
189190

0 commit comments

Comments
 (0)