Skip to content

Commit ad9b1ed

Browse files
committed
groundwork for #45009: rustc_dirty/clean enhancements
1 parent 51cd061 commit ad9b1ed

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

src/librustc/dep_graph/dep_node.rs

+19
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,25 @@ macro_rules! define_dep_nodes {
339339
Ok(DepNode::new_no_params(kind))
340340
}
341341
}
342+
343+
/// Used in testing
344+
pub fn has_label_string(label: &str) -> bool {
345+
match label {
346+
$(
347+
stringify!($variant) => true,
348+
)*
349+
_ => false,
350+
}
351+
}
352+
}
353+
354+
/// Contains variant => str representations for constructing
355+
/// DepNode groups for tests.
356+
#[allow(dead_code, non_upper_case_globals)]
357+
pub mod label_strs {
358+
$(
359+
pub const $variant: &'static str = stringify!($variant);
360+
)*
342361
}
343362
);
344363
}

src/librustc_incremental/persist/dirty_clean.rs

+45-12
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
//! previous revision to compare things to.
4040
//!
4141
42+
use std::collections::HashSet;
43+
use std::vec::Vec;
4244
use rustc::dep_graph::DepNode;
4345
use rustc::hir;
4446
use rustc::hir::def_id::DefId;
@@ -54,6 +56,8 @@ use rustc::ty::TyCtxt;
5456
const LABEL: &'static str = "label";
5557
const CFG: &'static str = "cfg";
5658

59+
type Labels = HashSet<String>;
60+
5761
pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
5862
// can't add `#[rustc_dirty]` etc without opting in to this feature
5963
if !tcx.sess.features.borrow().rustc_attrs {
@@ -87,23 +91,46 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
8791
}
8892

8993
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
90-
fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode {
91-
let def_path_hash = self.tcx.def_path_hash(def_id);
94+
fn labels(&self, attr: &Attribute) -> Labels {
9295
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
9396
if item.check_name(LABEL) {
9497
let value = expect_associated_value(self.tcx, &item);
95-
match DepNode::from_label_string(&value.as_str(), def_path_hash) {
96-
Ok(dep_node) => return dep_node,
97-
Err(()) => {
98-
self.tcx.sess.span_fatal(
99-
item.span,
100-
&format!("dep-node label `{}` not recognized", value));
101-
}
98+
return self.resolve_labels(&item, value.as_str().as_ref());
99+
}
100+
}
101+
self.tcx.sess.span_fatal(attr.span, "no `label` found");
102+
}
103+
104+
fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels {
105+
let mut out: Labels = HashSet::new();
106+
for label in value.split(',') {
107+
let label = label.trim();
108+
if DepNode::has_label_string(label) {
109+
if out.contains(label) {
110+
self.tcx.sess.span_fatal(
111+
item.span,
112+
&format!("dep-node label `{}` is repeated", label));
102113
}
114+
out.insert(label.to_string());
115+
} else {
116+
self.tcx.sess.span_fatal(
117+
item.span,
118+
&format!("dep-node label `{}` not recognized", label));
103119
}
104120
}
121+
out
122+
}
105123

106-
self.tcx.sess.span_fatal(attr.span, "no `label` found");
124+
fn dep_nodes(&self, labels: &Labels, def_id: DefId) -> Vec<DepNode> {
125+
let mut out = Vec::with_capacity(labels.len());
126+
let def_path_hash = self.tcx.def_path_hash(def_id);
127+
for label in labels.iter() {
128+
match DepNode::from_label_string(label, def_path_hash) {
129+
Ok(dep_node) => out.push(dep_node),
130+
Err(()) => unreachable!(),
131+
}
132+
}
133+
out
107134
}
108135

109136
fn dep_node_str(&self, dep_node: &DepNode) -> String {
@@ -150,12 +177,18 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
150177
if attr.check_name(ATTR_DIRTY) {
151178
if check_config(self.tcx, attr) {
152179
self.checked_attrs.insert(attr.id);
153-
self.assert_dirty(item_span, self.dep_node(attr, def_id));
180+
let labels = self.labels(attr);
181+
for dep_node in self.dep_nodes(&labels, def_id) {
182+
self.assert_dirty(item_span, dep_node);
183+
}
154184
}
155185
} else if attr.check_name(ATTR_CLEAN) {
156186
if check_config(self.tcx, attr) {
157187
self.checked_attrs.insert(attr.id);
158-
self.assert_clean(item_span, self.dep_node(attr, def_id));
188+
let labels = self.labels(attr);
189+
for dep_node in self.dep_nodes(&labels, def_id) {
190+
self.assert_clean(item_span, dep_node);
191+
}
159192
}
160193
}
161194
}

0 commit comments

Comments
 (0)