Skip to content

Commit

Permalink
rustc: Track stability of trait implementations
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Feb 17, 2015
1 parent f1bb6c2 commit 0cf2d00
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1761,7 +1761,7 @@ impl LintPass for Stability {
}

fn check_item(&mut self, cx: &Context, item: &ast::Item) {
stability::check_item(cx.tcx, item,
stability::check_item(cx.tcx, item, false,
&mut |id, sp, stab| self.lint(cx, id, sp, stab));
}

Expand Down
33 changes: 31 additions & 2 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
// name `__test`
if item.span == DUMMY_SP && item.ident.as_str() == "__test" { return }

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

/// Helper for discovering nodes to check for stability
pub fn check_item(tcx: &ty::ctxt, item: &ast::Item,
pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
match item.node {
ast::ItemExternCrate(_) => {
Expand All @@ -316,6 +316,35 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item,
let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
maybe_do_stability_check(tcx, id, item.span, cb);
}

// For implementations of traits, check the stability of each item
// individually as it's possible to have a stable trait with unstable
// items.
ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
let trait_did = tcx.def_map.borrow()[t.ref_id].def_id();
let trait_items = ty::trait_items(tcx, trait_did);

for impl_item in impl_items {
let (ident, span) = match *impl_item {
ast::MethodImplItem(ref method) => {
(match method.node {
ast::MethDecl(ident, _, _, _, _, _, _, _) => ident,
ast::MethMac(..) => unreachable!(),
}, method.span)
}
ast::TypeImplItem(ref typedef) => {
(typedef.ident, typedef.span)
}
};
let item = trait_items.iter().find(|item| {
item.name() == ident.name
}).unwrap();
if warn_about_defns {
maybe_do_stability_check(tcx, item.def_id(), span, cb);
}
}
}

_ => (/* pass */)
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/test/compile-fail/lint-stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ mod cross_crate {
impl UnstableTrait for S { } //~ WARNING use of unstable library feature

trait LocalTrait : UnstableTrait { } //~ WARNING use of unstable library feature

impl Trait for S {
fn trait_stable(&self) {}
fn trait_unstable(&self) {} //~ WARNING use of unstable library feature
}
}

mod inheritance {
Expand Down

0 comments on commit 0cf2d00

Please sign in to comment.