diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 88719a9bbdd..f446c4daefb 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -14,6 +14,7 @@ use session::Session; use lint; use middle::ty; +use middle::privacy::PublicItems; use metadata::csearch; use syntax::parse::token::InternedString; use syntax::codemap::{Span, DUMMY_SP}; @@ -45,14 +46,15 @@ pub struct Index { struct Annotator<'a> { sess: &'a Session, index: &'a mut Index, - parent: Option + parent: Option, + export_map: &'a PublicItems, } impl<'a> Annotator<'a> { // Determine the stability for a node based on its attributes and inherited // stability. The stability is recorded in the index and used as the parent. fn annotate(&mut self, id: NodeId, use_parent: bool, - attrs: &Vec, item_sp: Span, f: F) where + attrs: &Vec, item_sp: Span, f: F, required: bool) where F: FnOnce(&mut Annotator), { match attr::find_stability(self.sess.diagnostic(), attrs.as_slice(), item_sp) { @@ -70,7 +72,13 @@ impl<'a> Annotator<'a> { } None => { if use_parent { - self.parent.clone().map(|stab| self.index.local.insert(id, stab)); + if let Some(stab) = self.parent.clone() { + self.index.local.insert(id, stab); + } else if self.index.staged_api && required + && self.export_map.contains(&id) { + self.sess.span_err(item_sp, + "This node does not have a stability attribute"); + } } f(self); } @@ -93,11 +101,19 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> { _ => true, }; - self.annotate(i.id, use_parent, &i.attrs, i.span, |v| visit::walk_item(v, i)); + // In case of a `pub use ;`, we should not error since the stability + // is inherited from the module itself + let required = match i.node { + ast::ItemUse(_) => i.vis != ast::Public, + _ => true + }; + + self.annotate(i.id, use_parent, &i.attrs, i.span, + |v| visit::walk_item(v, i), required); if let ast::ItemStruct(ref sd, _) = i.node { sd.ctor_id.map(|id| { - self.annotate(id, true, &i.attrs, i.span, |_| {}) + self.annotate(id, true, &i.attrs, i.span, |_| {}, true) }); } } @@ -106,7 +122,7 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> { _: &'v Block, sp: Span, _: NodeId) { if let FkMethod(_, _, meth) = fk { // Methods are not already annotated, so we annotate it - self.annotate(meth.id, true, &meth.attrs, sp, |_| {}); + self.annotate(meth.id, true, &meth.attrs, sp, |_| {}, true); } // Items defined in a function body have no reason to have // a stability attribute, so we don't recurse. @@ -126,37 +142,38 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> { TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs, typedef.ty_param.span), }; - self.annotate(id, true, attrs, sp, |v| visit::walk_trait_item(v, t)); + self.annotate(id, true, attrs, sp, |v| visit::walk_trait_item(v, t), true); } fn visit_variant(&mut self, var: &Variant, g: &'v Generics) { self.annotate(var.node.id, true, &var.node.attrs, var.span, - |v| visit::walk_variant(v, var, g)) + |v| visit::walk_variant(v, var, g), true) } fn visit_struct_field(&mut self, s: &StructField) { self.annotate(s.node.id, true, &s.node.attrs, s.span, - |v| visit::walk_struct_field(v, s)); + |v| visit::walk_struct_field(v, s), true); } fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { - self.annotate(i.id, true, &i.attrs, i.span, |_| {}); + self.annotate(i.id, true, &i.attrs, i.span, |_| {}, true); } } impl Index { /// Construct the stability index for a crate being compiled. - pub fn build(&mut self, sess: &Session, krate: &Crate) { + pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems) { if !self.staged_api { return; } let mut annotator = Annotator { sess: sess, index: self, - parent: None + parent: None, + export_map: export_map, }; annotator.annotate(ast::CRATE_NODE_ID, true, &krate.attrs, krate.span, - |v| visit::walk_crate(v, krate)); + |v| visit::walk_crate(v, krate), true); } pub fn new(krate: &Crate) -> Index { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 166a1d6f809..8ede037594a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -627,7 +627,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, // Do not move this check past lint time(time_passes, "stability index", (), |_| - ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate)); + ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate, &public_items)); time(time_passes, "intrinsic checking", (), |_| middle::intrinsicck::check_crate(&ty_cx));