From 0cf2d00f0e034c8844bc9899b7e1df8c5eced60e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Feb 2015 13:56:06 -0800 Subject: [PATCH] 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. --- src/librustc/lint/builtin.rs | 2 +- src/librustc/middle/stability.rs | 33 +++++++++++++++++++++++-- src/test/compile-fail/lint-stability.rs | 5 ++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index d09e4bd97592..9d28ee7b6c63 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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)); } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index a086e91f4d9f..36bdca8c8e9a 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -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)) { 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 */) } } diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 5c187176fb2a..f9cdfa4f7d68 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -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 {