From 38dbcb2e3718eab4bac9f5a3ec8226d7ee4f40a7 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Wed, 11 Mar 2015 18:53:55 -0500 Subject: [PATCH] Check trait unsafety for defaulted traits --- src/libcore/marker.rs | 4 +- src/librustc_typeck/coherence/unsafety.rs | 99 ++++++++++--------- .../coherence-default-trait-impl.rs | 10 ++ 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index e980858c443b..0197ee82c774 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -39,7 +39,7 @@ pub unsafe trait Send : MarkerTrait { // empty. } -impl Send for .. { } +unsafe impl Send for .. { } impl !Send for *const T { } impl !Send for *mut T { } @@ -205,7 +205,7 @@ pub unsafe trait Sync : MarkerTrait { // Empty } -impl Sync for .. { } +unsafe impl Sync for .. { } impl !Sync for *const T { } impl !Sync for *mut T { } diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 867dea958856..e4926b119d5d 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -27,54 +27,65 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> { tcx: &'cx ty::ctxt<'tcx> } +impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { + fn check_unsafety_coherence(&mut self, item: &'v ast::Item, + unsafety: ast::Unsafety, + polarity: ast::ImplPolarity) { + match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) { + None => { + // Inherent impl. + match unsafety { + ast::Unsafety::Normal => { /* OK */ } + ast::Unsafety::Unsafe => { + span_err!(self.tcx.sess, item.span, E0197, + "inherent impls cannot be declared as unsafe"); + } + } + } + + Some(trait_ref) => { + let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id); + match (trait_def.unsafety, unsafety, polarity) { + (ast::Unsafety::Unsafe, + ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => { + span_err!(self.tcx.sess, item.span, E0198, + "negative implementations are not unsafe"); + } + + (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => { + span_err!(self.tcx.sess, item.span, E0199, + "implementing the trait `{}` is not unsafe", + trait_ref.user_string(self.tcx)); + } + + (ast::Unsafety::Unsafe, + ast::Unsafety::Normal, ast::ImplPolarity::Positive) => { + span_err!(self.tcx.sess, item.span, E0200, + "the trait `{}` requires an `unsafe impl` declaration", + trait_ref.user_string(self.tcx)); + } + + (ast::Unsafety::Unsafe, + ast::Unsafety::Normal, ast::ImplPolarity::Negative) | + (ast::Unsafety::Unsafe, + ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) | + (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => { + /* OK */ + } + } + } + } + } +} + impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v ast::Item) { match item.node { + ast::ItemDefaultImpl(unsafety, _) => { + self.check_unsafety_coherence(item, unsafety, ast::ImplPolarity::Positive); + } ast::ItemImpl(unsafety, polarity, _, _, _, _) => { - match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) { - None => { - // Inherent impl. - match unsafety { - ast::Unsafety::Normal => { /* OK */ } - ast::Unsafety::Unsafe => { - span_err!(self.tcx.sess, item.span, E0197, - "inherent impls cannot be declared as unsafe"); - } - } - } - - Some(trait_ref) => { - let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id); - match (trait_def.unsafety, unsafety, polarity) { - (ast::Unsafety::Unsafe, - ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => { - span_err!(self.tcx.sess, item.span, E0198, - "negative implementations are not unsafe"); - } - - (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => { - span_err!(self.tcx.sess, item.span, E0199, - "implementing the trait `{}` is not unsafe", - trait_ref.user_string(self.tcx)); - } - - (ast::Unsafety::Unsafe, - ast::Unsafety::Normal, ast::ImplPolarity::Positive) => { - span_err!(self.tcx.sess, item.span, E0200, - "the trait `{}` requires an `unsafe impl` declaration", - trait_ref.user_string(self.tcx)); - } - - (ast::Unsafety::Unsafe, - ast::Unsafety::Normal, ast::ImplPolarity::Negative) | - (ast::Unsafety::Unsafe, - ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) | - (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => { - /* OK */ - } - } - } - } + self.check_unsafety_coherence(item, unsafety, polarity); } _ => { } } diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs index 6bcbefb904d9..a5b317307379 100644 --- a/src/test/compile-fail/coherence-default-trait-impl.rs +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -21,4 +21,14 @@ impl MyTrait for .. {} impl MyTrait for .. {} //~^ ERROR conflicting implementations for trait `MyTrait` +trait MySafeTrait: MarkerTrait {} + +unsafe impl MySafeTrait for .. {} +//~^ ERROR implementing the trait `MySafeTrait` is not unsafe + +unsafe trait MyUnsafeTrait: MarkerTrait {} + +impl MyUnsafeTrait for .. {} +//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration + fn main() {}