From 5b895a833a6443046bbc8a6362b1a957cf68d1b4 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 11 Nov 2014 12:46:47 -0800 Subject: [PATCH 1/2] rustc: do not inherit #[stable] This patch tweaks the stability inheritance infrastructure so that `#{stable]` attributes are not inherited. Doing so solves two problems: 1. It allows us to mark module *names* as stable without accidentally marking the items they contain as stable. 2. It means that a `#[stable]` attribution must always appear directly on the item it applies to, which makes it easier for reviewers to catch changes to stable APIs. Fixes #17484 --- src/librustc/middle/stability.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 7f6a73c83fa..3b7ad9e8f6b 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -17,8 +17,7 @@ use syntax::{attr, visit}; use syntax::ast; use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant}; use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem}; -use syntax::ast::{TypeMethod, Method, Generics, StructDef, StructField}; -use syntax::ast::{Ident, TypeTraitItem}; +use syntax::ast::{TypeMethod, Method, Generics, StructField, TypeTraitItem}; use syntax::ast_util::is_local; use syntax::attr::Stability; use syntax::visit::{FnKind, FkMethod, Visitor}; @@ -48,9 +47,15 @@ impl Annotator { match attr::find_stability(attrs.as_slice()) { Some(stab) => { self.index.local.insert(id, stab.clone()); - let parent = replace(&mut self.parent, Some(stab)); - f(self); - self.parent = parent; + + // Don't inherit #[stable] + if stab.level != attr::Stable { + let parent = replace(&mut self.parent, Some(stab)); + f(self); + self.parent = parent; + } else { + f(self); + } } None => { self.parent.clone().map(|stab| self.index.local.insert(id, stab)); @@ -63,6 +68,15 @@ impl Annotator { impl<'v> Visitor<'v> for Annotator { fn visit_item(&mut self, i: &Item) { self.annotate(i.id, &i.attrs, |v| visit::walk_item(v, i)); + + match i.node { + ast::ItemStruct(ref sd, _) => { + sd.ctor_id.map(|id| { + self.annotate(id, &i.attrs, |_| {}) + }); + } + _ => {} + } } fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, @@ -95,13 +109,6 @@ impl<'v> Visitor<'v> for Annotator { self.annotate(var.node.id, &var.node.attrs, |v| visit::walk_variant(v, var, g)) } - fn visit_struct_def(&mut self, s: &StructDef, _: Ident, _: &Generics, _: NodeId) { - match s.ctor_id { - Some(id) => self.annotate(id, &vec![], |v| visit::walk_struct_def(v, s)), - None => visit::walk_struct_def(self, s) - } - } - fn visit_struct_field(&mut self, s: &StructField) { self.annotate(s.node.id, &s.node.attrs, |v| visit::walk_struct_field(v, s)); } From 83521954267b3555bfb3a185a187b2c2d929e453 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 11 Nov 2014 12:52:12 -0800 Subject: [PATCH 2/2] Update tests for new stability inheritance rules --- src/test/auxiliary/inherited_stability.rs | 12 ++++++++++-- src/test/compile-fail/lint-stability.rs | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/test/auxiliary/inherited_stability.rs b/src/test/auxiliary/inherited_stability.rs index 4016a76206b..5691ce3bfa7 100644 --- a/src/test/auxiliary/inherited_stability.rs +++ b/src/test/auxiliary/inherited_stability.rs @@ -18,10 +18,18 @@ pub fn stable() {} #[stable] pub mod stable_mod { + pub fn experimental() {} + + #[stable] + pub fn stable() {} +} + +#[unstable] +pub mod unstable_mod { #[experimental] pub fn experimental() {} - pub fn stable() {} + pub fn unstable() {} } pub mod experimental_mod { @@ -33,9 +41,9 @@ pub mod experimental_mod { #[stable] pub trait Stable { - #[experimental] fn experimental(&self); + #[stable] fn stable(&self); } diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 483a3b6d667..ba8559c8008 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -165,6 +165,9 @@ mod inheritance { stable_mod::experimental(); //~ ERROR use of experimental item stable_mod::stable(); + unstable_mod::experimental(); //~ ERROR use of experimental item + unstable_mod::unstable(); //~ ERROR use of unstable item + experimental_mod::experimental(); //~ ERROR use of experimental item experimental_mod::stable();