提交 928a2957 编写于 作者: B bors

Auto merge of #44983 - vitiral:dirty_clean_groups, r=michaelwoerister

groundwork for rustc_clean/dirty improvements

This is a WIP PR that needs mentoring from @michaelwoerister.

There are several TODOs but no outstanding questions (except for the main one -- **is this the right approach?**)

This is the plumbing for supporing groups in `rustc_clean(labels="...")`, as well as supporting an `except="..."` which will remove the excepted labels in the "clean" check and then assert that they are dirty (this is still TODO).

See the code TODO's and example comments for a rough design.

I'd like to know if this is the design you would like to do, and then I can go about actually filling out the groups and implementing the remaining logic.
......@@ -339,6 +339,25 @@ pub fn from_label_string(label: &str,
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);
)*
}
);
}
......
......@@ -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 @@
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 @@ fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
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);
}
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册