diff options
| author | Garrett Berg <googberg@gmail.com> | 2017-10-02 01:08:13 -0600 |
|---|---|---|
| committer | Garrett Berg <googberg@gmail.com> | 2017-10-04 07:20:59 -0600 |
| commit | ad9b1ed9c286d26666b7892145c5cae7f98488bc (patch) | |
| tree | 3990145e4bce033e11173ccbb7590920ff2075b4 | |
| parent | 51cd06170eccf91a2d93018e939473a8db18da92 (diff) | |
| download | rust-ad9b1ed9c286d26666b7892145c5cae7f98488bc.tar.gz rust-ad9b1ed9c286d26666b7892145c5cae7f98488bc.zip | |
groundwork for #45009: rustc_dirty/clean enhancements
| -rw-r--r-- | src/librustc/dep_graph/dep_node.rs | 19 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/dirty_clean.rs | 57 |
2 files changed, 64 insertions, 12 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 7a78765365d..eef99b0eb28 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -339,6 +339,25 @@ macro_rules! define_dep_nodes { Ok(DepNode::new_no_params(kind)) } } + + /// Used in testing + pub fn has_label_string(label: &str) -> bool { + match label { + $( + stringify!($variant) => true, + )* + _ => false, + } + } + } + + /// Contains variant => str representations for constructing + /// DepNode groups for tests. + #[allow(dead_code, non_upper_case_globals)] + pub mod label_strs { + $( + pub const $variant: &'static str = stringify!($variant); + )* } ); } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index a6d39a91863..186759d6219 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -39,6 +39,8 @@ //! previous revision to compare things to. //! +use std::collections::HashSet; +use std::vec::Vec; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; @@ -54,6 +56,8 @@ use rustc::ty::TyCtxt; const LABEL: &'static str = "label"; const CFG: &'static str = "cfg"; +type Labels = HashSet<String>; + 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 { @@ -87,23 +91,46 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> { } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { - fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { - let def_path_hash = self.tcx.def_path_hash(def_id); + fn labels(&self, attr: &Attribute) -> Labels { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { let value = expect_associated_value(self.tcx, &item); - match DepNode::from_label_string(&value.as_str(), def_path_hash) { - Ok(dep_node) => return dep_node, - Err(()) => { - self.tcx.sess.span_fatal( - item.span, - &format!("dep-node label `{}` not recognized", value)); - } + return self.resolve_labels(&item, value.as_str().as_ref()); + } + } + self.tcx.sess.span_fatal(attr.span, "no `label` found"); + } + + fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels { + let mut out: Labels = HashSet::new(); + for label in value.split(',') { + let label = label.trim(); + if DepNode::has_label_string(label) { + if out.contains(label) { + self.tcx.sess.span_fatal( + item.span, + &format!("dep-node label `{}` is repeated", label)); } + out.insert(label.to_string()); + } else { + self.tcx.sess.span_fatal( + item.span, + &format!("dep-node label `{}` not recognized", label)); } } + out + } - self.tcx.sess.span_fatal(attr.span, "no `label` found"); + fn dep_nodes(&self, labels: &Labels, def_id: DefId) -> Vec<DepNode> { + let mut out = Vec::with_capacity(labels.len()); + let def_path_hash = self.tcx.def_path_hash(def_id); + for label in labels.iter() { + match DepNode::from_label_string(label, def_path_hash) { + Ok(dep_node) => out.push(dep_node), + Err(()) => unreachable!(), + } + } + out } fn dep_node_str(&self, dep_node: &DepNode) -> String { @@ -150,12 +177,18 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if attr.check_name(ATTR_DIRTY) { if check_config(self.tcx, attr) { self.checked_attrs.insert(attr.id); - self.assert_dirty(item_span, self.dep_node(attr, def_id)); + let labels = self.labels(attr); + for dep_node in self.dep_nodes(&labels, def_id) { + self.assert_dirty(item_span, dep_node); + } } } else if attr.check_name(ATTR_CLEAN) { if check_config(self.tcx, attr) { self.checked_attrs.insert(attr.id); - self.assert_clean(item_span, self.dep_node(attr, def_id)); + let labels = self.labels(attr); + for dep_node in self.dep_nodes(&labels, def_id) { + self.assert_clean(item_span, dep_node); + } } } } |
