Skip to content

Commit 425c5d5

Browse files
committed
---
yaml --- r: 190430 b: refs/heads/snap-stage3 c: 4e789e0 h: refs/heads/master v: v3
1 parent 9161cc2 commit 425c5d5

12 files changed

+185
-91
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 857ac28867722111249b5c3ef68e32499bd11ea0
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 2e216896e4778738b4ed01e427f711f3a0b2c44c
4+
refs/heads/snap-stage3: 4e789e03be332c73836aae018eb83a47bc82d3c9
55
refs/heads/try: 1c28ab65017d74fc13d003f7c7a73d1a48e5406f
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d

branches/snap-stage3/src/librustc_typeck/coherence/impls.rs

Lines changed: 0 additions & 47 deletions
This file was deleted.

branches/snap-stage3/src/librustc_typeck/coherence/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ use syntax::visit;
4949
use util::nodemap::{DefIdMap, FnvHashMap};
5050
use util::ppaux::Repr;
5151

52-
mod impls;
5352
mod orphan;
5453
mod overlap;
5554
mod unsafety;
@@ -583,7 +582,6 @@ pub fn check_coherence(crate_context: &CrateCtxt) {
583582
inference_context: new_infer_ctxt(crate_context.tcx),
584583
inherent_impls: RefCell::new(FnvHashMap()),
585584
}.check(crate_context.tcx.map.krate());
586-
impls::check(crate_context.tcx);
587585
unsafety::check(crate_context.tcx);
588586
orphan::check(crate_context.tcx);
589587
overlap::check(crate_context.tcx);

branches/snap-stage3/src/librustc_typeck/coherence/orphan.rs

Lines changed: 89 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
3737
a trait or new type instead");
3838
}
3939
}
40-
}
4140

42-
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
43-
fn visit_item(&mut self, item: &ast::Item) {
41+
/// Checks exactly one impl for orphan rules and other such
42+
/// restrictions. In this fn, it can happen that multiple errors
43+
/// apply to a specific impl, so just return after reporting one
44+
/// to prevent inundating the user with a bunch of similar error
45+
/// reports.
46+
fn check_item(&self, item: &ast::Item) {
4447
let def_id = ast_util::local_def(item.id);
4548
match item.node {
4649
ast::ItemImpl(_, _, _, None, _, _) => {
@@ -63,6 +66,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
6366
span_err!(self.tcx.sess, item.span, E0118,
6467
"no base type found for inherent implementation; \
6568
implement a trait or new type instead");
69+
return;
6670
}
6771
}
6872
}
@@ -81,6 +85,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
8185
types defined in this crate; \
8286
only traits defined in the current crate can be \
8387
implemented for arbitrary types");
88+
return;
8489
}
8590
}
8691
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
@@ -90,11 +95,44 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
9095
some local type (e.g. `MyStruct<T>`); only traits defined in \
9196
the current crate can be implemented for a type parameter",
9297
param_ty.user_string(self.tcx));
98+
return;
9399
}
94100
}
95101
}
96102

97-
// Impls of a defaulted trait face additional rules.
103+
// In addition to the above rules, we restrict impls of defaulted traits
104+
// so that they can only be implemented on structs/enums. To see why this
105+
// restriction exists, consider the following example (#22978). Imagine
106+
// that crate A defines a defaulted trait `Foo` and a fn that operates
107+
// on pairs of types:
108+
//
109+
// ```
110+
// // Crate A
111+
// trait Foo { }
112+
// impl Foo for .. { }
113+
// fn two_foos<A:Foo,B:Foo>(..) {
114+
// one_foo::<(A,B)>(..)
115+
// }
116+
// fn one_foo<T:Foo>(..) { .. }
117+
// ```
118+
//
119+
// This type-checks fine; in particular the fn
120+
// `two_foos` is able to conclude that `(A,B):Foo`
121+
// because `A:Foo` and `B:Foo`.
122+
//
123+
// Now imagine that crate B comes along and does the following:
124+
//
125+
// ```
126+
// struct A { }
127+
// struct B { }
128+
// impl Foo for A { }
129+
// impl Foo for B { }
130+
// impl !Send for (A, B) { }
131+
// ```
132+
//
133+
// This final impl is legal according to the orpan
134+
// rules, but it invalidates the reasoning from
135+
// `two_foos` above.
98136
debug!("trait_ref={} trait_def_id={} trait_has_default_impl={}",
99137
trait_ref.repr(self.tcx),
100138
trait_def_id.repr(self.tcx),
@@ -104,29 +142,53 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
104142
trait_def_id.krate != ast::LOCAL_CRATE
105143
{
106144
let self_ty = trait_ref.self_ty();
107-
match self_ty.sty {
108-
ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) => {
109-
// The orphan check often rules this out,
110-
// but not always. For example, the orphan
111-
// check would accept `impl Send for
112-
// Box<SomethingLocal>`, but we want to
113-
// forbid that.
114-
if self_def_id.krate != ast::LOCAL_CRATE {
115-
self.tcx.sess.span_err(
116-
item.span,
117-
"cross-crate traits with a default impl \
145+
let opt_self_def_id = match self_ty.sty {
146+
ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) =>
147+
Some(self_def_id),
148+
ty::ty_uniq(..) =>
149+
self.tcx.lang_items.owned_box(),
150+
_ =>
151+
None
152+
};
153+
154+
let msg = match opt_self_def_id {
155+
// We only want to permit structs/enums, but not *all* structs/enums.
156+
// They must be local to the current crate, so that people
157+
// can't do `unsafe impl Send for Rc<SomethingLocal>` or
158+
// `unsafe impl !Send for Box<SomethingLocalAndSend>`.
159+
Some(self_def_id) => {
160+
if self_def_id.krate == ast::LOCAL_CRATE {
161+
None
162+
} else {
163+
Some(format!(
164+
"cross-crate traits with a default impl, like `{}`, \
118165
can only be implemented for a struct/enum type \
119-
defined in the current crate");
166+
defined in the current crate",
167+
ty::item_path_str(self.tcx, trait_def_id)))
120168
}
121169
}
122170
_ => {
123-
self.tcx.sess.span_err(
124-
item.span,
125-
"cross-crate traits with a default impl \
126-
can only be implemented for a struct or enum type");
171+
Some(format!(
172+
"cross-crate traits with a default impl, like `{}`, \
173+
can only be implemented for a struct/enum type, \
174+
not `{}`",
175+
ty::item_path_str(self.tcx, trait_def_id),
176+
self_ty.user_string(self.tcx)))
127177
}
178+
};
179+
180+
if let Some(msg) = msg {
181+
span_err!(self.tcx.sess, item.span, E0321, "{}", msg);
182+
return;
128183
}
129184
}
185+
186+
// Disallow *all* explicit impls of `Sized` for now.
187+
if Some(trait_def_id) == self.tcx.lang_items.sized_trait() {
188+
span_err!(self.tcx.sess, item.span, E0322,
189+
"explicit impls for the `Sized` trait are not permitted");
190+
return;
191+
}
130192
}
131193
ast::ItemDefaultImpl(..) => {
132194
// "Trait" impl
@@ -135,14 +197,20 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
135197
if trait_ref.def_id.krate != ast::LOCAL_CRATE {
136198
span_err!(self.tcx.sess, item.span, E0318,
137199
"cannot create default implementations for traits outside the \
138-
crate they're defined in; define a new trait instead.");
200+
crate they're defined in; define a new trait instead");
201+
return;
139202
}
140203
}
141204
_ => {
142205
// Not an impl
143206
}
144207
}
208+
}
209+
}
145210

211+
impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
212+
fn visit_item(&mut self, item: &ast::Item) {
213+
self.check_item(item);
146214
visit::walk_item(self, item);
147215
}
148216
}

branches/snap-stage3/src/librustc_typeck/diagnostics.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ register_diagnostics! {
175175
E0250, // expected constant expr for array length
176176
E0318, // can't create default impls for traits outside their crates
177177
E0319, // trait impls for defaulted traits allowed just for structs/enums
178-
E0320 // recursive overflow during dropck
178+
E0320, // recursive overflow during dropck
179+
E0321, // extended coherence rules for defaulted traits violated
180+
E0322 // cannot implement Sized explicitly
179181
}
180182

181183
__build_diagnostic_array! { DIAGNOSTICS }

branches/snap-stage3/src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ use std::marker::MarkerTrait;
1515

1616
pub trait DefaultedTrait : MarkerTrait { }
1717
impl DefaultedTrait for .. { }
18+
19+
pub struct Something<T> { t: T }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(optin_builtin_traits)]
12+
13+
use std::marker::Copy;
14+
15+
enum TestE {
16+
A
17+
}
18+
19+
struct MyType;
20+
21+
struct NotSync;
22+
impl !Sync for NotSync {}
23+
24+
impl Copy for TestE {}
25+
impl Copy for MyType {}
26+
impl Copy for (MyType, MyType) {}
27+
//~^ ERROR E0206
28+
29+
impl Copy for &'static NotSync {}
30+
//~^ ERROR E0206
31+
32+
impl Copy for [MyType] {}
33+
//~^ ERROR E0206
34+
35+
impl Copy for &'static [NotSync] {}
36+
//~^ ERROR E0206
37+
38+
fn main() {
39+
}

branches/snap-stage3/src/test/compile-fail/coherence-impls-builtin.rs renamed to branches/snap-stage3/src/test/compile-fail/coherence-impls-send.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#![feature(optin_builtin_traits)]
1212

13-
use std::marker::Send;
13+
use std::marker::Copy;
1414

1515
enum TestE {
1616
A
@@ -24,20 +24,17 @@ impl !Sync for NotSync {}
2424
unsafe impl Send for TestE {}
2525
unsafe impl Send for MyType {}
2626
unsafe impl Send for (MyType, MyType) {}
27-
//~^ ERROR builtin traits can only be implemented on structs or enums
27+
//~^ ERROR E0321
2828

2929
unsafe impl Send for &'static NotSync {}
30-
//~^ ERROR builtin traits can only be implemented on structs or enums
30+
//~^ ERROR E0321
3131

3232
unsafe impl Send for [MyType] {}
33-
//~^ ERROR builtin traits can only be implemented on structs or enums
33+
//~^ ERROR E0321
3434

3535
unsafe impl Send for &'static [NotSync] {}
36-
//~^ ERROR builtin traits can only be implemented on structs or enums
37-
//~^^ ERROR conflicting implementations for trait `core::marker::Send`
38-
39-
fn is_send<T: Send>() {}
36+
//~^ ERROR E0321
37+
//~| ERROR conflicting implementations
4038

4139
fn main() {
42-
is_send::<(MyType, TestE)>();
4340
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(optin_builtin_traits)]
12+
13+
use std::marker::Copy;
14+
15+
enum TestE {
16+
A
17+
}
18+
19+
struct MyType;
20+
21+
struct NotSync;
22+
impl !Sync for NotSync {}
23+
24+
impl Sized for TestE {} //~ ERROR E0322
25+
impl Sized for MyType {} //~ ERROR E0322
26+
impl Sized for (MyType, MyType) {} //~ ERROR E0322
27+
impl Sized for &'static NotSync {} //~ ERROR E0322
28+
impl Sized for [MyType] {} //~ ERROR E0322
29+
//~^ ERROR E0277
30+
impl Sized for &'static [NotSync] {} //~ ERROR E0322
31+
32+
fn main() {
33+
}

branches/snap-stage3/src/test/compile-fail/coherence-orphan.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ use lib::TheTrait;
1919

2020
struct TheType;
2121

22-
impl TheTrait<usize> for isize { } //~ ERROR E0117
22+
impl TheTrait<usize> for isize { }
23+
//~^ ERROR E0117
2324

2425
impl TheTrait<TheType> for isize { }
2526

2627
impl TheTrait<isize> for TheType { }
2728

28-
impl !Send for Vec<isize> { } //~ ERROR E0117
29-
//~^ ERROR conflicting
29+
impl !Send for Vec<isize> { }
30+
//~^ ERROR E0117
31+
//~| ERROR E0119
3032

3133
fn main() { }

0 commit comments

Comments
 (0)