Skip to content

Commit

Permalink
Check trait unsafety for defaulted traits
Browse files Browse the repository at this point in the history
  • Loading branch information
flaper87 committed Mar 20, 2015
1 parent 01d2429 commit 38dbcb2
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 43 deletions.
4 changes: 2 additions & 2 deletions src/libcore/marker.rs
Expand Up @@ -39,7 +39,7 @@ pub unsafe trait Send : MarkerTrait {
// empty.
}

impl Send for .. { }
unsafe impl Send for .. { }

impl<T> !Send for *const T { }
impl<T> !Send for *mut T { }
Expand Down Expand Up @@ -205,7 +205,7 @@ pub unsafe trait Sync : MarkerTrait {
// Empty
}

impl Sync for .. { }
unsafe impl Sync for .. { }

impl<T> !Sync for *const T { }
impl<T> !Sync for *mut T { }
Expand Down
93 changes: 52 additions & 41 deletions src/librustc_typeck/coherence/unsafety.rs
Expand Up @@ -27,55 +27,66 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
tcx: &'cx ty::ctxt<'tcx>
}

impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
match item.node {
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");
}
}
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");
}
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::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::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 */
}
}
(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, _, _, _, _) => {
self.check_unsafety_coherence(item, unsafety, polarity);
}
_ => { }
}

Expand Down
10 changes: 10 additions & 0 deletions src/test/compile-fail/coherence-default-trait-impl.rs
Expand Up @@ -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() {}

0 comments on commit 38dbcb2

Please sign in to comment.