auto merge of #18887 : aturon/rust/controlled-inherit, r=alexcrichton
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
This commit is contained in:
commit
15ba87f031
@ -17,8 +17,7 @@ use syntax::{attr, visit};
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
|
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
|
||||||
use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem};
|
use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem};
|
||||||
use syntax::ast::{TypeMethod, Method, Generics, StructDef, StructField};
|
use syntax::ast::{TypeMethod, Method, Generics, StructField, TypeTraitItem};
|
||||||
use syntax::ast::{Ident, TypeTraitItem};
|
|
||||||
use syntax::ast_util::is_local;
|
use syntax::ast_util::is_local;
|
||||||
use syntax::attr::Stability;
|
use syntax::attr::Stability;
|
||||||
use syntax::visit::{FnKind, FkMethod, Visitor};
|
use syntax::visit::{FnKind, FkMethod, Visitor};
|
||||||
@ -48,9 +47,15 @@ impl Annotator {
|
|||||||
match attr::find_stability(attrs.as_slice()) {
|
match attr::find_stability(attrs.as_slice()) {
|
||||||
Some(stab) => {
|
Some(stab) => {
|
||||||
self.index.local.insert(id, stab.clone());
|
self.index.local.insert(id, stab.clone());
|
||||||
let parent = replace(&mut self.parent, Some(stab));
|
|
||||||
f(self);
|
// Don't inherit #[stable]
|
||||||
self.parent = parent;
|
if stab.level != attr::Stable {
|
||||||
|
let parent = replace(&mut self.parent, Some(stab));
|
||||||
|
f(self);
|
||||||
|
self.parent = parent;
|
||||||
|
} else {
|
||||||
|
f(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
|
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
|
||||||
@ -63,6 +68,15 @@ impl Annotator {
|
|||||||
impl<'v> Visitor<'v> for Annotator {
|
impl<'v> Visitor<'v> for Annotator {
|
||||||
fn visit_item(&mut self, i: &Item) {
|
fn visit_item(&mut self, i: &Item) {
|
||||||
self.annotate(i.id, &i.attrs, |v| visit::walk_item(v, i));
|
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,
|
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))
|
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) {
|
fn visit_struct_field(&mut self, s: &StructField) {
|
||||||
self.annotate(s.node.id, &s.node.attrs, |v| visit::walk_struct_field(v, s));
|
self.annotate(s.node.id, &s.node.attrs, |v| visit::walk_struct_field(v, s));
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,18 @@ pub fn stable() {}
|
|||||||
|
|
||||||
#[stable]
|
#[stable]
|
||||||
pub mod stable_mod {
|
pub mod stable_mod {
|
||||||
|
pub fn experimental() {}
|
||||||
|
|
||||||
|
#[stable]
|
||||||
|
pub fn stable() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable]
|
||||||
|
pub mod unstable_mod {
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn experimental() {}
|
pub fn experimental() {}
|
||||||
|
|
||||||
pub fn stable() {}
|
pub fn unstable() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod experimental_mod {
|
pub mod experimental_mod {
|
||||||
@ -33,9 +41,9 @@ pub mod experimental_mod {
|
|||||||
|
|
||||||
#[stable]
|
#[stable]
|
||||||
pub trait Stable {
|
pub trait Stable {
|
||||||
#[experimental]
|
|
||||||
fn experimental(&self);
|
fn experimental(&self);
|
||||||
|
|
||||||
|
#[stable]
|
||||||
fn stable(&self);
|
fn stable(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +165,9 @@ mod inheritance {
|
|||||||
stable_mod::experimental(); //~ ERROR use of experimental item
|
stable_mod::experimental(); //~ ERROR use of experimental item
|
||||||
stable_mod::stable();
|
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::experimental(); //~ ERROR use of experimental item
|
||||||
experimental_mod::stable();
|
experimental_mod::stable();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user