Skip to content

Commit 38dbcb2

Browse files
committed
Check trait unsafety for defaulted traits
1 parent 01d2429 commit 38dbcb2

File tree

3 files changed

+64
-43
lines changed

3 files changed

+64
-43
lines changed

src/libcore/marker.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub unsafe trait Send : MarkerTrait {
3939
// empty.
4040
}
4141

42-
impl Send for .. { }
42+
unsafe impl Send for .. { }
4343

4444
impl<T> !Send for *const T { }
4545
impl<T> !Send for *mut T { }
@@ -205,7 +205,7 @@ pub unsafe trait Sync : MarkerTrait {
205205
// Empty
206206
}
207207

208-
impl Sync for .. { }
208+
unsafe impl Sync for .. { }
209209

210210
impl<T> !Sync for *const T { }
211211
impl<T> !Sync for *mut T { }

src/librustc_typeck/coherence/unsafety.rs

+52-41
Original file line numberDiff line numberDiff line change
@@ -27,55 +27,66 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
2727
tcx: &'cx ty::ctxt<'tcx>
2828
}
2929

30-
impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
31-
fn visit_item(&mut self, item: &'v ast::Item) {
32-
match item.node {
33-
ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
34-
match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
35-
None => {
36-
// Inherent impl.
37-
match unsafety {
38-
ast::Unsafety::Normal => { /* OK */ }
39-
ast::Unsafety::Unsafe => {
40-
span_err!(self.tcx.sess, item.span, E0197,
41-
"inherent impls cannot be declared as unsafe");
42-
}
43-
}
30+
impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
31+
fn check_unsafety_coherence(&mut self, item: &'v ast::Item,
32+
unsafety: ast::Unsafety,
33+
polarity: ast::ImplPolarity) {
34+
match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
35+
None => {
36+
// Inherent impl.
37+
match unsafety {
38+
ast::Unsafety::Normal => { /* OK */ }
39+
ast::Unsafety::Unsafe => {
40+
span_err!(self.tcx.sess, item.span, E0197,
41+
"inherent impls cannot be declared as unsafe");
4442
}
43+
}
44+
}
4545

46-
Some(trait_ref) => {
47-
let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
48-
match (trait_def.unsafety, unsafety, polarity) {
49-
(ast::Unsafety::Unsafe,
50-
ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
51-
span_err!(self.tcx.sess, item.span, E0198,
52-
"negative implementations are not unsafe");
53-
}
46+
Some(trait_ref) => {
47+
let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
48+
match (trait_def.unsafety, unsafety, polarity) {
49+
(ast::Unsafety::Unsafe,
50+
ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
51+
span_err!(self.tcx.sess, item.span, E0198,
52+
"negative implementations are not unsafe");
53+
}
5454

55-
(ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
56-
span_err!(self.tcx.sess, item.span, E0199,
57-
"implementing the trait `{}` is not unsafe",
58-
trait_ref.user_string(self.tcx));
59-
}
55+
(ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
56+
span_err!(self.tcx.sess, item.span, E0199,
57+
"implementing the trait `{}` is not unsafe",
58+
trait_ref.user_string(self.tcx));
59+
}
6060

61-
(ast::Unsafety::Unsafe,
62-
ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
63-
span_err!(self.tcx.sess, item.span, E0200,
64-
"the trait `{}` requires an `unsafe impl` declaration",
65-
trait_ref.user_string(self.tcx));
66-
}
61+
(ast::Unsafety::Unsafe,
62+
ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
63+
span_err!(self.tcx.sess, item.span, E0200,
64+
"the trait `{}` requires an `unsafe impl` declaration",
65+
trait_ref.user_string(self.tcx));
66+
}
6767

68-
(ast::Unsafety::Unsafe,
69-
ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
70-
(ast::Unsafety::Unsafe,
71-
ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
72-
(ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
73-
/* OK */
74-
}
75-
}
68+
(ast::Unsafety::Unsafe,
69+
ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
70+
(ast::Unsafety::Unsafe,
71+
ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
72+
(ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
73+
/* OK */
7674
}
7775
}
7876
}
77+
}
78+
}
79+
}
80+
81+
impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
82+
fn visit_item(&mut self, item: &'v ast::Item) {
83+
match item.node {
84+
ast::ItemDefaultImpl(unsafety, _) => {
85+
self.check_unsafety_coherence(item, unsafety, ast::ImplPolarity::Positive);
86+
}
87+
ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
88+
self.check_unsafety_coherence(item, unsafety, polarity);
89+
}
7990
_ => { }
8091
}
8192

src/test/compile-fail/coherence-default-trait-impl.rs

+10
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,14 @@ impl MyTrait for .. {}
2121
impl MyTrait for .. {}
2222
//~^ ERROR conflicting implementations for trait `MyTrait`
2323

24+
trait MySafeTrait: MarkerTrait {}
25+
26+
unsafe impl MySafeTrait for .. {}
27+
//~^ ERROR implementing the trait `MySafeTrait` is not unsafe
28+
29+
unsafe trait MyUnsafeTrait: MarkerTrait {}
30+
31+
impl MyUnsafeTrait for .. {}
32+
//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
33+
2434
fn main() {}

0 commit comments

Comments
 (0)