Skip to content

Commit

Permalink
RFC-2027: Add tests for new legal syntax and wf/coherence
Browse files Browse the repository at this point in the history
  • Loading branch information
bovinebuddha committed Jan 15, 2019
1 parent a18ee9a commit c516035
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Check that unsafe trait object do not implement themselves
// automatically

#![feature(object_safe_for_dispatch)]

trait Trait: Sized {
fn call(&self);
}

fn takes_t<S: Trait>(s: S) {
s.call();
}

fn takes_t_obj(t: &dyn Trait) {
takes_t(t); //~ ERROR E0277
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
--> $DIR/coherence-unsafe-trait-object-impl.rs:15:5
|
LL | takes_t(t); //~ ERROR E0277
| ^^^^^^^ the trait `Trait` is not implemented for `&dyn Trait`
|
note: required by `takes_t`
--> $DIR/coherence-unsafe-trait-object-impl.rs:10:1
|
LL | fn takes_t<S: Trait>(s: S) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Check that we if we get ahold of an object unsafe trait
// object with auto traits and lifetimes, we can downcast it
//
// compile-pass

#![feature(object_safe_for_dispatch)]

trait Trait: Sized {}

fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait {
t
}

fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't))
-> &'b (dyn Trait + 't)
where
'a: 'b,
't: 'a + 'b,
{
t
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Check that we can manually implement an object
// unsafe trait for its trait object
//
// run-pass

#![feature(object_safe_for_dispatch)]

trait Bad {
fn stat() -> char {
'A'
}
fn virt(&self) -> char {
'B'
}
fn indirect(&self) -> char {
Self::stat()
}
}

trait Good {
fn good_virt(&self) -> char {
panic!()
}
fn good_indirect(&self) -> char {
panic!()
}
}

impl<'a> Bad for dyn Bad + 'a {
fn stat() -> char {
'C'
}
fn virt(&self) -> char {
'D'
}
}

struct Struct {}

impl Bad for Struct {}

impl Good for Struct {}

fn main() {
let s = Struct {};

let mut res = String::new();

// Directly call static
res.push(Struct::stat()); // "A"
res.push(<dyn Bad>::stat()); // "AC"

let good: &dyn Good = &s;

// These look similar enough...
let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) };

// Call virtual
res.push(s.virt()); // "ACB"
res.push(bad.virt()); // "ACBD"

// Indirectly call static
res.push(s.indirect()); // "ACBDA"
res.push(bad.indirect()); // "ACBDAC"

if &res != "ACBDAC" {
panic!();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Check that we can statically dispatch methods for object
// unsafe trait objects, directly and indirectly
//
// compile-pass

#![feature(object_safe_for_dispatch)]

trait Statics {
fn plain() {}
fn generic<T>() {}
}

trait Trait: Sized {}

impl<'a> Statics for dyn Trait + 'a {}

fn static_poly<T: Statics + ?Sized>() {
T::plain();
T::generic::<usize>();
}

fn inferred_poly<T: Statics + ?Sized>(t: &T) {
static_poly::<T>();
T::plain();
T::generic::<usize>();
}

fn call(t: &dyn Trait) {
static_poly::<dyn Trait>();
inferred_poly(t);
}

fn main() {
static_poly::<dyn Trait>();
<dyn Trait>::plain();
<dyn Trait>::generic::<usize>()
}
18 changes: 18 additions & 0 deletions src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Check that we do not allow casts or coercions
// to object unsafe trait objects inside a Box

#![feature(object_safe_for_dispatch)]

trait Trait: Sized {}

struct S;

impl Trait for S {}

fn takes_box(t: Box<dyn Trait>) {}

fn main() {
Box::new(S) as Box<dyn Trait>; //~ ERROR E0038
let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038
takes_box(Box::new(S)); //~ ERROR E0038
}
30 changes: 30 additions & 0 deletions src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33
|
LL | let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
= note: required when trying to coerce from type `std::boxed::Box<S>` to type 'std::boxed::Box<dyn Trait>`

error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15
|
LL | takes_box(Box::new(S)); //~ ERROR E0038
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
= note: required when trying to coerce from type `std::boxed::Box<S>` to type 'std::boxed::Box<(dyn Trait + 'static)>`

error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:20
|
LL | Box::new(S) as Box<dyn Trait>; //~ ERROR E0038
| ^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
= note: required by cast to type 'std::boxed::Box<dyn Trait>'

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0038`.
18 changes: 18 additions & 0 deletions src/test/ui/wf/wf-convert-unsafe-trait-obj.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Check that we do not allow casts or coercions
// to object unsafe trait objects by ref

#![feature(object_safe_for_dispatch)]

trait Trait: Sized {}

struct S;

impl Trait for S {}

fn takes_trait(t: &dyn Trait) {}

fn main() {
&S as &dyn Trait; //~ ERROR E0038
let t: &dyn Trait = &S; //~ ERROR E0038
takes_trait(&S); //~ ERROR E0038
}
30 changes: 30 additions & 0 deletions src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/wf-convert-unsafe-trait-obj.rs:16:25
|
LL | let t: &dyn Trait = &S; //~ ERROR E0038
| ^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
= note: required when trying to coerce from type `&S` to type '&dyn Trait`

error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/wf-convert-unsafe-trait-obj.rs:17:17
|
LL | takes_trait(&S); //~ ERROR E0038
| ^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
= note: required when trying to coerce from type `&S` to type '&dyn Trait`

error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/wf-convert-unsafe-trait-obj.rs:15:11
|
LL | &S as &dyn Trait; //~ ERROR E0038
| ^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
= note: required by cast to type '&dyn Trait'

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0038`.
29 changes: 29 additions & 0 deletions src/test/ui/wf/wf-unsafe-trait-obj-match.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Check that we do not allow coercions to object
// unsafe trait objects in match arms

#![feature(object_safe_for_dispatch)]

trait Trait: Sized {}

struct S;

impl Trait for S {}

struct R;

impl Trait for R {}

fn opt() -> Option<()> {
Some(())
}

fn main() {
match opt() { //~ ERROR E0308
Some(()) => &S,
None => &R,
}
let t: &dyn Trait = match opt() { //~ ERROR E0308
Some(()) => &S,
None => &R,
};
}
29 changes: 29 additions & 0 deletions src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error[E0308]: match arms have incompatible types
--> $DIR/wf-unsafe-trait-obj-match.rs:21:5
|
LL | / match opt() { //~ ERROR E0308
LL | | Some(()) => &S,
LL | | None => &R,
| | -- match arm with an incompatible type
LL | | }
| |_____^ expected struct `S`, found struct `R`
|
= note: expected type `&S`
found type `&R`

error[E0308]: match arms have incompatible types
--> $DIR/wf-unsafe-trait-obj-match.rs:25:25
|
LL | let t: &dyn Trait = match opt() { //~ ERROR E0308
| _________________________^
LL | | Some(()) => &S,
| | -- match arm with an incompatible type
LL | | None => &R,
LL | | };
| |_____^
|
= note: required when trying to coerce from type `&S` to type '&dyn Trait`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.

0 comments on commit c516035

Please sign in to comment.