Skip to content

Commit 6ec5a0f

Browse files
committed
Error when #![staged_api] crates are missing stability markers
1 parent 0b9e227 commit 6ec5a0f

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

src/librustc/middle/stability.rs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use session::Session;
1515
use lint;
1616
use middle::ty;
17+
use middle::privacy::PublicItems;
1718
use metadata::csearch;
1819
use syntax::parse::token::InternedString;
1920
use syntax::codemap::{Span, DUMMY_SP};
@@ -45,14 +46,15 @@ pub struct Index {
4546
struct Annotator<'a> {
4647
sess: &'a Session,
4748
index: &'a mut Index,
48-
parent: Option<Stability>
49+
parent: Option<Stability>,
50+
export_map: &'a PublicItems,
4951
}
5052

5153
impl<'a> Annotator<'a> {
5254
// Determine the stability for a node based on its attributes and inherited
5355
// stability. The stability is recorded in the index and used as the parent.
5456
fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
55-
attrs: &Vec<Attribute>, item_sp: Span, f: F) where
57+
attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
5658
F: FnOnce(&mut Annotator),
5759
{
5860
match attr::find_stability(self.sess.diagnostic(), attrs.as_slice(), item_sp) {
@@ -70,7 +72,13 @@ impl<'a> Annotator<'a> {
7072
}
7173
None => {
7274
if use_parent {
73-
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
75+
if let Some(stab) = self.parent.clone() {
76+
self.index.local.insert(id, stab);
77+
} else if self.index.staged_api && required
78+
&& self.export_map.contains(&id) {
79+
self.sess.span_err(item_sp,
80+
"This node does not have a stability attribute");
81+
}
7482
}
7583
f(self);
7684
}
@@ -93,11 +101,19 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> {
93101
_ => true,
94102
};
95103

96-
self.annotate(i.id, use_parent, &i.attrs, i.span, |v| visit::walk_item(v, i));
104+
// In case of a `pub use <mod>;`, we should not error since the stability
105+
// is inherited from the module itself
106+
let required = match i.node {
107+
ast::ItemUse(_) => i.vis != ast::Public,
108+
_ => true
109+
};
110+
111+
self.annotate(i.id, use_parent, &i.attrs, i.span,
112+
|v| visit::walk_item(v, i), required);
97113

98114
if let ast::ItemStruct(ref sd, _) = i.node {
99115
sd.ctor_id.map(|id| {
100-
self.annotate(id, true, &i.attrs, i.span, |_| {})
116+
self.annotate(id, true, &i.attrs, i.span, |_| {}, true)
101117
});
102118
}
103119
}
@@ -106,7 +122,7 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> {
106122
_: &'v Block, sp: Span, _: NodeId) {
107123
if let FkMethod(_, _, meth) = fk {
108124
// Methods are not already annotated, so we annotate it
109-
self.annotate(meth.id, true, &meth.attrs, sp, |_| {});
125+
self.annotate(meth.id, true, &meth.attrs, sp, |_| {}, true);
110126
}
111127
// Items defined in a function body have no reason to have
112128
// a stability attribute, so we don't recurse.
@@ -126,37 +142,38 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> {
126142
TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs,
127143
typedef.ty_param.span),
128144
};
129-
self.annotate(id, true, attrs, sp, |v| visit::walk_trait_item(v, t));
145+
self.annotate(id, true, attrs, sp, |v| visit::walk_trait_item(v, t), true);
130146
}
131147

132148
fn visit_variant(&mut self, var: &Variant, g: &'v Generics) {
133149
self.annotate(var.node.id, true, &var.node.attrs, var.span,
134-
|v| visit::walk_variant(v, var, g))
150+
|v| visit::walk_variant(v, var, g), true)
135151
}
136152

137153
fn visit_struct_field(&mut self, s: &StructField) {
138154
self.annotate(s.node.id, true, &s.node.attrs, s.span,
139-
|v| visit::walk_struct_field(v, s));
155+
|v| visit::walk_struct_field(v, s), true);
140156
}
141157

142158
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
143-
self.annotate(i.id, true, &i.attrs, i.span, |_| {});
159+
self.annotate(i.id, true, &i.attrs, i.span, |_| {}, true);
144160
}
145161
}
146162

147163
impl Index {
148164
/// Construct the stability index for a crate being compiled.
149-
pub fn build(&mut self, sess: &Session, krate: &Crate) {
165+
pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems) {
150166
if !self.staged_api {
151167
return;
152168
}
153169
let mut annotator = Annotator {
154170
sess: sess,
155171
index: self,
156-
parent: None
172+
parent: None,
173+
export_map: export_map,
157174
};
158175
annotator.annotate(ast::CRATE_NODE_ID, true, &krate.attrs, krate.span,
159-
|v| visit::walk_crate(v, krate));
176+
|v| visit::walk_crate(v, krate), true);
160177
}
161178

162179
pub fn new(krate: &Crate) -> Index {

src/librustc_driver/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
627627

628628
// Do not move this check past lint
629629
time(time_passes, "stability index", (), |_|
630-
ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate));
630+
ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate, &public_items));
631631

632632
time(time_passes, "intrinsic checking", (), |_|
633633
middle::intrinsicck::check_crate(&ty_cx));

0 commit comments

Comments
 (0)