Check trait unsafety for defaulted traits
This commit is contained in:
parent
01d24297eb
commit
38dbcb2e37
3 changed files with 67 additions and 46 deletions
|
|
@ -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 { }
|
||||
|
|
@ -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 { }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue