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.
This commit is contained in:
Alex Crichton 2015-02-17 13:56:06 -08:00
parent f1bb6c2f46
commit 0cf2d00f0e
3 changed files with 37 additions and 3 deletions

View File

@ -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));
}

View File

@ -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);
}
@ -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(_) => {
@ -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 */)
}
}

View File

@ -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 {