diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 4b3e0d29101e4..1df6761506993 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -914,6 +914,7 @@ pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) { pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_id(expression.id); + walk_list!(visitor, visit_attribute, expression.attrs.iter()); match expression.node { ExprBox(ref subexpression) => { visitor.visit_expr(subexpression) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 798bc6e9f9856..a0bcb54af320f 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -46,6 +46,7 @@ use rustc::dep_graph::{DepGraphQuery, DepNode}; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir::intravisit; use syntax::ast::{self, Attribute, NestedMetaItem}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use syntax_pos::Span; @@ -73,17 +74,32 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let query = tcx.dep_graph.query(); debug!("query-nodes: {:?}", query.nodes()); let krate = tcx.hir.krate(); - krate.visit_all_item_likes(&mut DirtyCleanVisitor { + let mut dirty_clean_visitor = DirtyCleanVisitor { tcx: tcx, query: &query, dirty_inputs: dirty_inputs, - }); + checked_attrs: FxHashSet(), + }; + krate.visit_all_item_likes(&mut dirty_clean_visitor); + + let mut all_attrs = FindAllAttrs { + tcx: tcx, + attr_names: vec![ATTR_DIRTY, ATTR_CLEAN], + found_attrs: vec![], + }; + intravisit::walk_crate(&mut all_attrs, krate); + + // Note that we cannot use the existing "unused attribute"-infrastructure + // here, since that is running before trans. This is also the reason why + // all trans-specific attributes are `Whitelisted` in syntax::feature_gate. + all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs); } pub struct DirtyCleanVisitor<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, query: &'a DepGraphQuery, dirty_inputs: FxHashSet>, + checked_attrs: FxHashSet, } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { @@ -109,7 +125,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { dep_node.map_def(|&def_id| Some(self.tcx.item_path_str(def_id))).unwrap() } - fn assert_dirty(&self, item: &hir::Item, dep_node: DepNode) { + fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); match dep_node { @@ -121,7 +137,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if !self.dirty_inputs.contains(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( - item.span, + item_span, &format!("`{:?}` not found in dirty set, but should be dirty", dep_node_str)); } @@ -132,14 +148,14 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if self.query.contains_node(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( - item.span, + item_span, &format!("`{:?}` found in dep graph, but should be dirty", dep_node_str)); } } } } - fn assert_clean(&self, item: &hir::Item, dep_node: DepNode) { + fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); match dep_node { @@ -150,7 +166,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if self.dirty_inputs.contains(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( - item.span, + item_span, &format!("`{:?}` found in dirty-node set, but should be clean", dep_node_str)); } @@ -160,35 +176,43 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if !self.query.contains_node(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( - item.span, + item_span, &format!("`{:?}` not found in dep graph, but should be clean", dep_node_str)); } } } } -} -impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> { - fn visit_item(&mut self, item: &'tcx hir::Item) { - let def_id = self.tcx.hir.local_def_id(item.id); + fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) { + let def_id = self.tcx.hir.local_def_id(item_id); for attr in self.tcx.get_attrs(def_id).iter() { if attr.check_name(ATTR_DIRTY) { if check_config(self.tcx, attr) { - self.assert_dirty(item, self.dep_node(attr, def_id)); + self.checked_attrs.insert(attr.id); + self.assert_dirty(item_span, self.dep_node(attr, def_id)); } } else if attr.check_name(ATTR_CLEAN) { if check_config(self.tcx, attr) { - self.assert_clean(item, self.dep_node(attr, def_id)); + self.checked_attrs.insert(attr.id); + self.assert_clean(item_span, self.dep_node(attr, def_id)); } } } } +} + +impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> { + fn visit_item(&mut self, item: &'tcx hir::Item) { + self.check_item(item.id, item.span); + } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + fn visit_trait_item(&mut self, item: &hir::TraitItem) { + self.check_item(item.id, item.span); } - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + fn visit_impl_item(&mut self, item: &hir::ImplItem) { + self.check_item(item.id, item.span); } } @@ -201,11 +225,25 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.dep_graph.with_ignore(||{ let krate = tcx.hir.krate(); - krate.visit_all_item_likes(&mut DirtyCleanMetadataVisitor { + let mut dirty_clean_visitor = DirtyCleanMetadataVisitor { tcx: tcx, prev_metadata_hashes: prev_metadata_hashes, current_metadata_hashes: current_metadata_hashes, - }); + checked_attrs: FxHashSet(), + }; + krate.visit_all_item_likes(&mut dirty_clean_visitor); + + let mut all_attrs = FindAllAttrs { + tcx: tcx, + attr_names: vec![ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA], + found_attrs: vec![], + }; + intravisit::walk_crate(&mut all_attrs, krate); + + // Note that we cannot use the existing "unused attribute"-infrastructure + // here, since that is running before trans. This is also the reason why + // all trans-specific attributes are `Whitelisted` in syntax::feature_gate. + all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs); }); } @@ -213,34 +251,43 @@ pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> { tcx: TyCtxt<'a, 'tcx, 'tcx>, prev_metadata_hashes: &'m FxHashMap, current_metadata_hashes: &'m FxHashMap, + checked_attrs: FxHashSet, } impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { fn visit_item(&mut self, item: &'tcx hir::Item) { - let def_id = self.tcx.hir.local_def_id(item.id); + self.check_item(item.id, item.span); + } + + fn visit_trait_item(&mut self, item: &hir::TraitItem) { + self.check_item(item.id, item.span); + } + + fn visit_impl_item(&mut self, item: &hir::ImplItem) { + self.check_item(item.id, item.span); + } +} + +impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { + + fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) { + let def_id = self.tcx.hir.local_def_id(item_id); for attr in self.tcx.get_attrs(def_id).iter() { if attr.check_name(ATTR_DIRTY_METADATA) { if check_config(self.tcx, attr) { - self.assert_state(false, def_id, item.span); + self.checked_attrs.insert(attr.id); + self.assert_state(false, def_id, item_span); } } else if attr.check_name(ATTR_CLEAN_METADATA) { if check_config(self.tcx, attr) { - self.assert_state(true, def_id, item.span); + self.checked_attrs.insert(attr.id); + self.assert_state(true, def_id, item_span); } } } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - } -} - -impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { - fn assert_state(&self, should_be_clean: bool, def_id: DefId, span: Span) { let item_path = self.tcx.item_path_str(def_id); debug!("assert_state({})", item_path); @@ -274,7 +321,7 @@ impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { /// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan /// for a `cfg="foo"` attribute and check whether we have a cfg /// flag called `foo`. -fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool { +fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool { debug!("check_config(attr={:?})", attr); let config = &tcx.sess.parse_sess.config; debug!("check_config: config={:?}", config); @@ -304,3 +351,47 @@ fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name { tcx.sess.span_fatal(item.span, &msg); } } + + +// A visitor that collects all #[rustc_dirty]/#[rustc_clean] attributes from +// the HIR. It is used to verfiy that we really ran checks for all annotated +// nodes. +pub struct FindAllAttrs<'a, 'tcx:'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + attr_names: Vec<&'static str>, + found_attrs: Vec<&'tcx Attribute>, +} + +impl<'a, 'tcx> FindAllAttrs<'a, 'tcx> { + + fn is_active_attr(&mut self, attr: &Attribute) -> bool { + for attr_name in &self.attr_names { + if attr.check_name(attr_name) && check_config(self.tcx, attr) { + return true; + } + } + + false + } + + fn report_unchecked_attrs(&self, checked_attrs: &FxHashSet) { + for attr in &self.found_attrs { + if !checked_attrs.contains(&attr.id) { + self.tcx.sess.span_err(attr.span, &format!("found unchecked \ + #[rustc_dirty]/#[rustc_clean] attribute")); + } + } + } +} + +impl<'a, 'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { + intravisit::NestedVisitorMap::All(&self.tcx.hir) + } + + fn visit_attribute(&mut self, attr: &'tcx Attribute) { + if self.is_active_attr(attr) { + self.found_attrs.push(attr); + } + } +} diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 5c37bc133596d..fd9ac61046e3a 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -39,9 +39,7 @@ impl Foo { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn method_name2() { } } @@ -60,16 +58,47 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn method_body() { println!("Hello, world!"); } } -// Change Method Privacy ----------------------------------------------------------- + +// Change Method Body (inlined) ------------------------------------------------ +// +// This should affect the method itself, but not the impl. +#[cfg(cfail1)] +impl Foo { + #[inline] + pub fn method_body_inlined() { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl Foo { + #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + #[inline] + pub fn method_body_inlined() { + println!("Hello, world!"); + } +} + + +// Change Method Privacy ------------------------------------------------------- #[cfg(cfail1)] impl Foo { pub fn method_privacy() { } @@ -142,13 +171,11 @@ impl Foo { impl Foo { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_method_to_impl1(&self) { } - #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_method_to_impl2(&self) { } } @@ -188,9 +215,13 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] + // At the moment we explicitly ignore argument names in metadata, since they + // are not used in downstream crates (except in rustdoc) + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_parameter_name(&self, b: i64) { } } @@ -252,9 +283,13 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] + // At the moment we explicitly ignore argument names in metadata, since they + // are not used in downstream crates (except in rustdoc) + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } @@ -465,7 +500,7 @@ impl Bar { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -486,7 +521,7 @@ impl Bar { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -507,7 +542,7 @@ impl Bar { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -528,7 +563,7 @@ impl Bar { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index bc401ae93404f..94698506ec53f 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -316,8 +316,10 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn method(mut self) {} diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index 15094492248e6..30e376f04fb87 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -46,9 +46,7 @@ impl ChangeMethodNameTrait for Foo { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub trait ChangeMethodNameTrait { - #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn method_name2(); } @@ -59,16 +57,14 @@ pub trait ChangeMethodNameTrait { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeMethodNameTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn method_name2() { } } // Change Method Body ----------------------------------------------------------- // -// This should affect the method itself, but not the trait. +// This should affect the method itself, but not the impl. pub trait ChangeMethodBodyTrait { fn method_name(); @@ -85,16 +81,50 @@ impl ChangeMethodBodyTrait for Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeMethodBodyTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name() { + () + } +} + +// Change Method Body (inlined fn) --------------------------------------------- +// +// This should affect the method itself, but not the impl. + +pub trait ChangeMethodBodyTraitInlined { + fn method_name(); +} + +#[cfg(cfail1)] +impl ChangeMethodBodyTraitInlined for Foo { + #[inline] + fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeMethodBodyTraitInlined for Foo { + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] + #[inline] fn method_name() { () } } -// Change Method Selfness ----------------------------------------------------------- +// Change Method Selfness ------------------------------------------------------ #[cfg(cfail1)] pub trait ChangeMethodSelfnessTrait { @@ -447,7 +477,7 @@ impl ChangeSelfTypeOfImpl for u32 { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeSelfTypeOfImpl for u64 { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -472,7 +502,7 @@ impl AddLifetimeBoundToImplParameter for T { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl AddLifetimeBoundToImplParameter for T { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -497,7 +527,7 @@ impl AddTraitBoundToImplParameter for T { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl AddTraitBoundToImplParameter for T { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] diff --git a/src/test/incremental/unchecked_dirty_clean.rs b/src/test/incremental/unchecked_dirty_clean.rs new file mode 100644 index 0000000000000..a81e884f39eac --- /dev/null +++ b/src/test/incremental/unchecked_dirty_clean.rs @@ -0,0 +1,44 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// revisions: rpass1 cfail2 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] + +// Sanity check for the dirty-clean system. We add #[rustc_dirty]/#[rustc_clean] +// attributes in places that are not checked and make sure that this causes an +// error. + +fn main() { + + #[rustc_dirty(label="Hir", cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + { + // empty block + } + + #[rustc_clean(label="Hir", cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + { + // empty block + } +} + +struct _Struct { + #[rustc_dirty(label="Hir", cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + _field1: i32, + + #[rustc_clean(label="Hir", cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + _field2: i32, +} diff --git a/src/test/incremental/unchecked_dirty_clean_metadata.rs b/src/test/incremental/unchecked_dirty_clean_metadata.rs new file mode 100644 index 0000000000000..4017b4d4ba9ae --- /dev/null +++ b/src/test/incremental/unchecked_dirty_clean_metadata.rs @@ -0,0 +1,45 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// revisions: rpass1 cfail2 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] + +// Sanity check for the dirty-clean system. We add +// #[rustc_metadata_dirty]/#[rustc_metadata_clean] attributes in places that +// are not checked and make sure that this causes an error. + +fn main() { + + #[rustc_metadata_dirty(cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + { + // empty block + } + + #[rustc_metadata_clean(cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + { + // empty block + } +} + +struct _Struct { + #[rustc_metadata_dirty(cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + _field1: i32, + + #[rustc_metadata_clean(cfg="cfail2")] + //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute + _field2: i32, +} +