From 90718ea4bc8b5dafd3bf345ccea8a787a967a14f Mon Sep 17 00:00:00 2001 From: Mathias Blikstad Date: Sat, 12 Jan 2019 14:50:18 +0100 Subject: [PATCH] RFC-2027: Add tests for new legal syntax and wf/coherence --- .../coherence-unsafe-trait-object-impl.rs | 18 +++++ .../coherence-unsafe-trait-object-impl.stderr | 15 ++++ .../downcast-unsafe-trait-objects.rs | 23 +++++++ .../manual-self-impl-for-unsafe-obj.rs | 69 +++++++++++++++++++ .../static-dispatch-unsafe-object.rs | 37 ++++++++++ .../ui/wf/wf-convert-unsafe-trait-obj-box.rs | 18 +++++ .../wf/wf-convert-unsafe-trait-obj-box.stderr | 30 ++++++++ src/test/ui/wf/wf-convert-unsafe-trait-obj.rs | 18 +++++ .../ui/wf/wf-convert-unsafe-trait-obj.stderr | 30 ++++++++ src/test/ui/wf/wf-unsafe-trait-obj-match.rs | 29 ++++++++ .../ui/wf/wf-unsafe-trait-obj-match.stderr | 29 ++++++++ 11 files changed, 316 insertions(+) create mode 100644 src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs create mode 100644 src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr create mode 100644 src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs create mode 100644 src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs create mode 100644 src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs create mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs create mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr create mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj.rs create mode 100644 src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr create mode 100644 src/test/ui/wf/wf-unsafe-trait-obj-match.rs create mode 100644 src/test/ui/wf/wf-unsafe-trait-obj-match.stderr diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs new file mode 100644 index 0000000000000..9859a226efd00 --- /dev/null +++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -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: S) { + s.call(); +} + +fn takes_t_obj(t: &dyn Trait) { + takes_t(t); //~ ERROR E0277 +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr new file mode 100644 index 0000000000000..f398991c8af6e --- /dev/null +++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr @@ -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: S) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs new file mode 100644 index 0000000000000..bc2878d9a8455 --- /dev/null +++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs @@ -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() {} diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs new file mode 100644 index 0000000000000..1dea401226569 --- /dev/null +++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -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(::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!(); + } +} diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs new file mode 100644 index 0000000000000..199dd73dc85a5 --- /dev/null +++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs @@ -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() {} +} + +trait Trait: Sized {} + +impl<'a> Statics for dyn Trait + 'a {} + +fn static_poly() { + T::plain(); + T::generic::(); +} + +fn inferred_poly(t: &T) { + static_poly::(); + T::plain(); + T::generic::(); +} + +fn call(t: &dyn Trait) { + static_poly::(); + inferred_poly(t); +} + +fn main() { + static_poly::(); + ::plain(); + ::generic::() +} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs new file mode 100644 index 0000000000000..ffdb49a3be5c7 --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -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) {} + +fn main() { + Box::new(S) as Box; //~ ERROR E0038 + let t_box: Box = Box::new(S); //~ ERROR E0038 + takes_box(Box::new(S)); //~ ERROR E0038 +} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr new file mode 100644 index 0000000000000..bb09e5050488d --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr @@ -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 = 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` to type 'std::boxed::Box` + +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` 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; //~ 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' + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs new file mode 100644 index 0000000000000..143b854ed6b2d --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -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 +} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr new file mode 100644 index 0000000000000..d01f3e50aab2d --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr @@ -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`. diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.rs b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs new file mode 100644 index 0000000000000..7c83f348fe994 --- /dev/null +++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs @@ -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, + }; +} diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr new file mode 100644 index 0000000000000..b378fb37b3f37 --- /dev/null +++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr @@ -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`.