Skip to content

Commit 0cf2d00

Browse files
committed
rustc: Track stability of trait implementations
Previously an implementation of a stable trait allows implementations of unstable methods. This updates the stability pass to ensure that all items of an impl block of a trait are indeed stable on the trait itself.
1 parent f1bb6c2 commit 0cf2d00

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

src/librustc/lint/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,7 @@ impl LintPass for Stability {
17611761
}
17621762

17631763
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
1764-
stability::check_item(cx.tcx, item,
1764+
stability::check_item(cx.tcx, item, false,
17651765
&mut |id, sp, stab| self.lint(cx, id, sp, stab));
17661766
}
17671767

src/librustc/middle/stability.rs

+31-2
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
283283
// name `__test`
284284
if item.span == DUMMY_SP && item.ident.as_str() == "__test" { return }
285285

286-
check_item(self.tcx, item,
286+
check_item(self.tcx, item, true,
287287
&mut |id, sp, stab| self.check(id, sp, stab));
288288
visit::walk_item(self, item);
289289
}
@@ -302,7 +302,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
302302
}
303303

304304
/// Helper for discovering nodes to check for stability
305-
pub fn check_item(tcx: &ty::ctxt, item: &ast::Item,
305+
pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
306306
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
307307
match item.node {
308308
ast::ItemExternCrate(_) => {
@@ -316,6 +316,35 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item,
316316
let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
317317
maybe_do_stability_check(tcx, id, item.span, cb);
318318
}
319+
320+
// For implementations of traits, check the stability of each item
321+
// individually as it's possible to have a stable trait with unstable
322+
// items.
323+
ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
324+
let trait_did = tcx.def_map.borrow()[t.ref_id].def_id();
325+
let trait_items = ty::trait_items(tcx, trait_did);
326+
327+
for impl_item in impl_items {
328+
let (ident, span) = match *impl_item {
329+
ast::MethodImplItem(ref method) => {
330+
(match method.node {
331+
ast::MethDecl(ident, _, _, _, _, _, _, _) => ident,
332+
ast::MethMac(..) => unreachable!(),
333+
}, method.span)
334+
}
335+
ast::TypeImplItem(ref typedef) => {
336+
(typedef.ident, typedef.span)
337+
}
338+
};
339+
let item = trait_items.iter().find(|item| {
340+
item.name() == ident.name
341+
}).unwrap();
342+
if warn_about_defns {
343+
maybe_do_stability_check(tcx, item.def_id(), span, cb);
344+
}
345+
}
346+
}
347+
319348
_ => (/* pass */)
320349
}
321350
}

src/test/compile-fail/lint-stability.rs

+5
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ mod cross_crate {
133133
impl UnstableTrait for S { } //~ WARNING use of unstable library feature
134134

135135
trait LocalTrait : UnstableTrait { } //~ WARNING use of unstable library feature
136+
137+
impl Trait for S {
138+
fn trait_stable(&self) {}
139+
fn trait_unstable(&self) {} //~ WARNING use of unstable library feature
140+
}
136141
}
137142

138143
mod inheritance {

0 commit comments

Comments
 (0)