Skip to content

Commit c30d624

Browse files
committed
RFC-2027: Add tests for new legal syntax and wf/coherence
1 parent b57bd84 commit c30d624

11 files changed

+314
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Check that unsafe trait object do not implement themselves
2+
// automatically
3+
4+
#![feature(object_safe_for_dispatch)]
5+
6+
trait Trait: Sized {
7+
fn call(&self);
8+
}
9+
10+
fn takes_t<S: Trait>(s: S) {
11+
s.call();
12+
}
13+
14+
fn takes_t_obj(t: &dyn Trait) {
15+
takes_t(t); //~ ERROR E0277
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
2+
--> $DIR/coherence-unsafe-trait-object-impl.rs:15:5
3+
|
4+
LL | takes_t(t); //~ ERROR E0277
5+
| ^^^^^^^ the trait `Trait` is not implemented for `&dyn Trait`
6+
|
7+
note: required by `takes_t`
8+
--> $DIR/coherence-unsafe-trait-object-impl.rs:10:1
9+
|
10+
LL | fn takes_t<S: Trait>(s: S) {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Check that we if we get ahold of an object unsafe trait
2+
// object with auto traits and lifetimes, we can downcast it
3+
//
4+
// compile-pass
5+
6+
#![feature(object_safe_for_dispatch)]
7+
8+
trait Trait: Sized {}
9+
10+
fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait {
11+
t
12+
}
13+
14+
fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't))
15+
-> &'b (dyn Trait + 't)
16+
where
17+
'a: 'b,
18+
't: 'a + 'b,
19+
{
20+
t
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Check that we can manually implement an object
2+
// unsafe trait for its trait object
3+
//
4+
// run-pass
5+
6+
#![feature(object_safe_for_dispatch)]
7+
8+
trait Bad {
9+
fn stat() -> char {
10+
'A'
11+
}
12+
fn virt(&self) -> char {
13+
'B'
14+
}
15+
fn indirect(&self) -> char {
16+
Self::stat()
17+
}
18+
}
19+
20+
trait Good {
21+
fn good_virt(&self) -> char {
22+
panic!()
23+
}
24+
fn good_indirect(&self) -> char {
25+
panic!()
26+
}
27+
}
28+
29+
impl<'a> Bad for dyn Bad + 'a {
30+
fn stat() -> char {
31+
'C'
32+
}
33+
fn virt(&self) -> char {
34+
'D'
35+
}
36+
}
37+
38+
struct Struct {}
39+
40+
impl Bad for Struct {}
41+
42+
impl Good for Struct {}
43+
44+
fn main() {
45+
let s = Struct {};
46+
47+
let mut res = String::new();
48+
49+
// Directly call static
50+
res.push(Struct::stat()); // "A"
51+
res.push(<dyn Bad>::stat()); // "AC"
52+
53+
let good: &dyn Good = &s;
54+
55+
// These look similar enough...
56+
let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) };
57+
58+
// Call virtual
59+
res.push(s.virt()); // "ACB"
60+
res.push(bad.virt()); // "ACBD"
61+
62+
// Indirectly call static
63+
res.push(s.indirect()); // "ACBDA"
64+
res.push(bad.indirect()); // "ACBDAC"
65+
66+
if &res != "ACBDAC" {
67+
panic!();
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Check that we can statically dispatch methods for object
2+
// unsafe trait objects, directly and indirectly
3+
//
4+
// compile-pass
5+
6+
#![feature(object_safe_for_dispatch)]
7+
8+
trait Statics {
9+
fn plain() {}
10+
fn generic<T>() {}
11+
}
12+
13+
trait Trait: Sized {}
14+
15+
impl<'a> Statics for dyn Trait + 'a {}
16+
17+
fn static_poly<T: Statics + ?Sized>() {
18+
T::plain();
19+
T::generic::<usize>();
20+
}
21+
22+
fn inferred_poly<T: Statics + ?Sized>(t: &T) {
23+
static_poly::<T>();
24+
T::plain();
25+
T::generic::<usize>();
26+
}
27+
28+
fn call(t: &dyn Trait) {
29+
static_poly::<dyn Trait>();
30+
inferred_poly(t);
31+
}
32+
33+
fn main() {
34+
static_poly::<dyn Trait>();
35+
<dyn Trait>::plain();
36+
<dyn Trait>::generic::<usize>()
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Check that we do not allow casts or coercions
2+
// to object unsafe trait objects inside a Box
3+
4+
#![feature(object_safe_for_dispatch)]
5+
6+
trait Trait: Sized {}
7+
8+
struct S;
9+
10+
impl Trait for S {}
11+
12+
fn takes_box(t: Box<dyn Trait>) {}
13+
14+
fn main() {
15+
Box::new(S) as Box<dyn Trait>; //~ ERROR E0038
16+
let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038
17+
takes_box(Box::new(S)); //~ ERROR E0038
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0038]: the trait `Trait` cannot be made into an object
2+
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33
3+
|
4+
LL | let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038
5+
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
6+
|
7+
= note: the trait cannot require that `Self : Sized`
8+
= note: required when trying to coerce from type `std::boxed::Box<S>` to type 'std::boxed::Box<dyn Trait>`
9+
10+
error[E0038]: the trait `Trait` cannot be made into an object
11+
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15
12+
|
13+
LL | takes_box(Box::new(S)); //~ ERROR E0038
14+
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
15+
|
16+
= note: the trait cannot require that `Self : Sized`
17+
= note: required when trying to coerce from type `std::boxed::Box<S>` to type 'std::boxed::Box<(dyn Trait + 'static)>`
18+
19+
error[E0038]: the trait `Trait` cannot be made into an object
20+
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:20
21+
|
22+
LL | Box::new(S) as Box<dyn Trait>; //~ ERROR E0038
23+
| ^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
24+
|
25+
= note: the trait cannot require that `Self : Sized`
26+
= note: required by cast to type 'std::boxed::Box<dyn Trait>'
27+
28+
error: aborting due to 3 previous errors
29+
30+
For more information about this error, try `rustc --explain E0038`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Check that we do not allow casts or coercions
2+
// to object unsafe trait objects by ref
3+
4+
#![feature(object_safe_for_dispatch)]
5+
6+
trait Trait: Sized {}
7+
8+
struct S;
9+
10+
impl Trait for S {}
11+
12+
fn takes_trait(t: &dyn Trait) {}
13+
14+
fn main() {
15+
&S as &dyn Trait; //~ ERROR E0038
16+
let t: &dyn Trait = &S; //~ ERROR E0038
17+
takes_trait(&S); //~ ERROR E0038
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0038]: the trait `Trait` cannot be made into an object
2+
--> $DIR/wf-convert-unsafe-trait-obj.rs:16:25
3+
|
4+
LL | let t: &dyn Trait = &S; //~ ERROR E0038
5+
| ^^ the trait `Trait` cannot be made into an object
6+
|
7+
= note: the trait cannot require that `Self : Sized`
8+
= note: required when trying to coerce from type `&S` to type '&dyn Trait`
9+
10+
error[E0038]: the trait `Trait` cannot be made into an object
11+
--> $DIR/wf-convert-unsafe-trait-obj.rs:17:17
12+
|
13+
LL | takes_trait(&S); //~ ERROR E0038
14+
| ^^ the trait `Trait` cannot be made into an object
15+
|
16+
= note: the trait cannot require that `Self : Sized`
17+
= note: required when trying to coerce from type `&S` to type '&dyn Trait`
18+
19+
error[E0038]: the trait `Trait` cannot be made into an object
20+
--> $DIR/wf-convert-unsafe-trait-obj.rs:15:11
21+
|
22+
LL | &S as &dyn Trait; //~ ERROR E0038
23+
| ^^^^^^^^^^ the trait `Trait` cannot be made into an object
24+
|
25+
= note: the trait cannot require that `Self : Sized`
26+
= note: required by cast to type '&dyn Trait'
27+
28+
error: aborting due to 3 previous errors
29+
30+
For more information about this error, try `rustc --explain E0038`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Check that we do not allow coercions to object
2+
// unsafe trait objects in match arms
3+
4+
#![feature(object_safe_for_dispatch)]
5+
6+
trait Trait: Sized {}
7+
8+
struct S;
9+
10+
impl Trait for S {}
11+
12+
struct R;
13+
14+
impl Trait for R {}
15+
16+
fn opt() -> Option<()> {
17+
Some(())
18+
}
19+
20+
fn main() {
21+
match opt() { //~ ERROR E0308
22+
Some(()) => &S,
23+
None => &R,
24+
}
25+
let t: &dyn Trait = match opt() { //~ ERROR E0308
26+
Some(()) => &S,
27+
None => &R,
28+
};
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0308]: match arms have incompatible types
2+
--> $DIR/wf-unsafe-trait-obj-match.rs:23:17
3+
|
4+
LL | / match opt() { //~ ERROR E0308
5+
LL | | Some(()) => &S,
6+
| | -- this is found to be of type `&S`
7+
LL | | None => &R,
8+
| | ^^ expected struct `S`, found struct `R`
9+
LL | | }
10+
| |_____- `match` arms have incompatible types
11+
|
12+
= note: expected type `&S`
13+
found type `&R`
14+
15+
error[E0038]: the trait `Trait` cannot be made into an object
16+
--> $DIR/wf-unsafe-trait-obj-match.rs:26:21
17+
|
18+
LL | Some(()) => &S,
19+
| ^^ the trait `Trait` cannot be made into an object
20+
|
21+
= note: the trait cannot require that `Self : Sized`
22+
= note: required when trying to coerce from type `&S` to type '&dyn Trait`
23+
24+
error: aborting due to 2 previous errors
25+
26+
Some errors occurred: E0038, E0308.
27+
For more information about an error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)