From 9549fbd6255fb9f7e4ce1a8859fae7335465e014 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 5 Nov 2019 02:18:39 +0000 Subject: [PATCH] Added tests. --- .../infer/error_reporting/mod.rs | 4 +- .../feature-gate-c_variadic.rs | 0 .../feature-gate-c_variadic.stderr | 0 .../feature-gate-static-nobundle-2.rs | 0 .../feature-gate-static-nobundle-2.stderr | 0 .../feature-gate-trait_upcasting.rs | 5 +- .../feature-gate-trait_upcasting.stderr | 10 +- ...exe.rs => anon-trait-static-method-exe.rs} | 0 ...pl_trait.rs => conservative-impl-trait.rs} | 0 src/test/ui/traits/trait-upcasting/basic.rs | 80 +++++++++ .../cyclic-trait-resolution.rs | 13 ++ .../cyclic-trait-resolution.stderr | 16 ++ src/test/ui/traits/trait-upcasting/diamond.rs | 108 ++++++++++++ .../traits/trait-upcasting/invalid-upcast.rs | 68 ++++++++ .../trait-upcasting/invalid-upcast.stderr | 135 +++++++++++++++ .../issue-11515-upcast-fn_mut-fn.rs} | 3 +- .../issue-11515-upcast-fn_mut-fn.stderr} | 3 +- .../ui/traits/trait-upcasting/lifetime.rs | 70 ++++++++ src/test/ui/traits/trait-upcasting/struct.rs | 155 ++++++++++++++++++ .../traits/trait-upcasting/subtrait-method.rs | 51 ++++++ .../trait-upcasting/subtrait-method.stderr | 68 ++++++++ .../trait-upcasting/upcast-fn_mut-fn-pass.rs | 12 ++ 22 files changed, 792 insertions(+), 9 deletions(-) rename src/test/ui/{feature-gate => feature-gates}/feature-gate-c_variadic.rs (100%) rename src/test/ui/{feature-gate => feature-gates}/feature-gate-c_variadic.stderr (100%) rename src/test/ui/{feature-gate => feature-gates}/feature-gate-static-nobundle-2.rs (100%) rename src/test/ui/{feature-gate => feature-gates}/feature-gate-static-nobundle-2.stderr (100%) rename src/test/ui/traits/{anon_trait_static_method_exe.rs => anon-trait-static-method-exe.rs} (100%) rename src/test/ui/traits/{conservative_impl_trait.rs => conservative-impl-trait.rs} (100%) create mode 100644 src/test/ui/traits/trait-upcasting/basic.rs create mode 100644 src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs create mode 100644 src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr create mode 100644 src/test/ui/traits/trait-upcasting/diamond.rs create mode 100644 src/test/ui/traits/trait-upcasting/invalid-upcast.rs create mode 100644 src/test/ui/traits/trait-upcasting/invalid-upcast.stderr rename src/test/ui/{issues/issue-11515.rs => traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs} (67%) rename src/test/ui/{issues/issue-11515.stderr => traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.stderr} (76%) create mode 100644 src/test/ui/traits/trait-upcasting/lifetime.rs create mode 100644 src/test/ui/traits/trait-upcasting/struct.rs create mode 100644 src/test/ui/traits/trait-upcasting/subtrait-method.rs create mode 100644 src/test/ui/traits/trait-upcasting/subtrait-method.stderr create mode 100644 src/test/ui/traits/trait-upcasting/upcast-fn_mut-fn-pass.rs diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 9fcd4a1f9d0cd..3633ead054429 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1686,7 +1686,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let trait_ref = Binder::bind(TraitRef::identity(self.tcx, exp_found.found)); let supertraits = crate::traits::util::supertraits(self.tcx, trait_ref); if supertraits.into_iter().any(|trait_ref| trait_ref.def_id() == exp_found.expected) { - diag.note("add `#![feature(trait_upcasting)]` to the crate attributes to enable"); + diag.note( + "add `#![feature(trait_upcasting)]` to the crate attributes to enable \ + trait upcasting"); } } diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.rs b/src/test/ui/feature-gates/feature-gate-c_variadic.rs similarity index 100% rename from src/test/ui/feature-gate/feature-gate-c_variadic.rs rename to src/test/ui/feature-gates/feature-gate-c_variadic.rs diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.stderr b/src/test/ui/feature-gates/feature-gate-c_variadic.stderr similarity index 100% rename from src/test/ui/feature-gate/feature-gate-c_variadic.stderr rename to src/test/ui/feature-gates/feature-gate-c_variadic.stderr diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle-2.rs similarity index 100% rename from src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs rename to src/test/ui/feature-gates/feature-gate-static-nobundle-2.rs diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr similarity index 100% rename from src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr rename to src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr diff --git a/src/test/ui/feature-gates/feature-gate-trait_upcasting.rs b/src/test/ui/feature-gates/feature-gate-trait_upcasting.rs index f0facfd97fb7a..0abe68ee05924 100644 --- a/src/test/ui/feature-gates/feature-gate-trait_upcasting.rs +++ b/src/test/ui/feature-gates/feature-gate-trait_upcasting.rs @@ -10,7 +10,8 @@ fn main() { let bar: &dyn Bar = &(); let foo: &dyn Foo = bar; //~^ ERROR mismatched types [E0308] - //~| NOTE expected type `&dyn Foo` //~| NOTE expected trait `Foo`, found trait `Bar` - //~| NOTE add `#![feature(trait_upcasting)]` to the crate attributes to enable + //~| NOTE expected due to this + //~| NOTE expected reference `&dyn Foo` + //~| NOTE add `#![feature(trait_upcasting)]` to the crate attributes to enable trait upcasting } diff --git a/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr b/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr index 452913f163ae2..a2e2986188e69 100644 --- a/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr +++ b/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr @@ -2,11 +2,13 @@ error[E0308]: mismatched types --> $DIR/feature-gate-trait_upcasting.rs:11:25 | LL | let foo: &dyn Foo = bar; - | ^^^ expected trait `Foo`, found trait `Bar` + | -------- ^^^ expected trait `Foo`, found trait `Bar` + | | + | expected due to this | - = note: add `#![feature(trait_upcasting)]` to the crate attributes to enable - = note: expected type `&dyn Foo` - found type `&dyn Bar` + = note: expected reference `&dyn Foo` + found reference `&dyn Bar` + = note: add `#![feature(trait_upcasting)]` to the crate attributes to enable trait upcasting error: aborting due to previous error diff --git a/src/test/ui/traits/anon_trait_static_method_exe.rs b/src/test/ui/traits/anon-trait-static-method-exe.rs similarity index 100% rename from src/test/ui/traits/anon_trait_static_method_exe.rs rename to src/test/ui/traits/anon-trait-static-method-exe.rs diff --git a/src/test/ui/traits/conservative_impl_trait.rs b/src/test/ui/traits/conservative-impl-trait.rs similarity index 100% rename from src/test/ui/traits/conservative_impl_trait.rs rename to src/test/ui/traits/conservative-impl-trait.rs diff --git a/src/test/ui/traits/trait-upcasting/basic.rs b/src/test/ui/traits/trait-upcasting/basic.rs new file mode 100644 index 0000000000000..78ddbe088887a --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/basic.rs @@ -0,0 +1,80 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { 10 } + + fn z(&self) -> i32 { 11 } + + fn y(&self) -> i32 { 12 } +} + +trait Bar: Foo { + fn b(&self) -> i32 { 20 } + + fn w(&self) -> i32 { 21 } +} + +trait Baz: Bar { + fn c(&self) -> i32 { 30 } +} + +impl Foo for i32 { + fn a(&self) -> i32 { 100 } +} + +impl Bar for i32 { + fn b(&self) -> i32 { 200 } +} + +impl Baz for i32 { + fn c(&self) -> i32 { 300 } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + let _: &(dyn Send + Sync) = baz; + let _: &dyn Send = baz; + let _: &dyn Sync = baz; + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let bar: &dyn Bar = baz; + let _: &dyn std::fmt::Debug = bar; + let _: &(dyn Send + Sync) = bar; + let _: &dyn Send = bar; + let _: &dyn Sync = bar; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let foo: &dyn Foo = baz; + let _: &dyn std::fmt::Debug = foo; + let _: &(dyn Send + Sync) = foo; + let _: &dyn Send = foo; + let _: &dyn Sync = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let foo: &dyn Foo = bar; + let _: &dyn std::fmt::Debug = foo; + let _: &(dyn Send + Sync) = foo; + let _: &dyn Send = foo; + let _: &dyn Sync = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} diff --git a/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs new file mode 100644 index 0000000000000..1666b7ba292b2 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs @@ -0,0 +1,13 @@ +trait A: B + A {} +//~^ ERROR cycle detected when computing the supertraits of `A` [E0391] + +trait B {} + +impl A for () {} + +impl B for () {} + +fn main() { + let a: Box = Box::new(()); + let _b: Box = a; +} diff --git a/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr new file mode 100644 index 0000000000000..7a04c5d0dbbe5 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the supertraits of `A` + --> $DIR/cyclic-trait-resolution.rs:1:14 + | +LL | trait A: B + A {} + | ^ + | + = note: ...which again requires computing the supertraits of `A`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cyclic-trait-resolution.rs:1:1 + | +LL | trait A: B + A {} + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/traits/trait-upcasting/diamond.rs b/src/test/ui/traits/trait-upcasting/diamond.rs new file mode 100644 index 0000000000000..531b40d83f9f7 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/diamond.rs @@ -0,0 +1,108 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { 10 } + + fn z(&self) -> i32 { 11 } + + fn y(&self) -> i32 { 12 } +} + +trait Bar1: Foo { + fn b(&self) -> i32 { 20 } + + fn w(&self) -> i32 { 21 } +} + +trait Bar2: Foo { + fn c(&self) -> i32 { 30 } + + fn v(&self) -> i32 { 31 } +} + +trait Baz: Bar1 + Bar2 { + fn d(&self) -> i32 { 40 } +} + +impl Foo for i32 { + fn a(&self) -> i32 { 100 } +} + +impl Bar1 for i32 { + fn b(&self) -> i32 { 200 } +} + +impl Bar2 for i32 { + fn c(&self) -> i32 { 300 } +} + +impl Baz for i32 { + fn d(&self) -> i32 { 400 } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + let _: &(dyn Send + Sync) = baz; + let _: &dyn Send = baz; + let _: &dyn Sync = baz; + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.d(), 400); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + assert_eq!(baz.v(), 31); + + let bar1: &dyn Bar1 = baz; + let _: &dyn std::fmt::Debug = bar1; + let _: &(dyn Send + Sync) = bar1; + let _: &dyn Send = bar1; + let _: &dyn Sync = bar1; + assert_eq!(*bar1, 1); + assert_eq!(bar1.a(), 100); + assert_eq!(bar1.b(), 200); + assert_eq!(bar1.z(), 11); + assert_eq!(bar1.y(), 12); + assert_eq!(bar1.w(), 21); + + let bar2: &dyn Bar2 = baz; + let _: &dyn std::fmt::Debug = bar2; + let _: &(dyn Send + Sync) = bar2; + let _: &dyn Send = bar2; + let _: &dyn Sync = bar2; + assert_eq!(*bar2, 1); + assert_eq!(bar2.a(), 100); + assert_eq!(bar2.c(), 300); + assert_eq!(bar2.z(), 11); + assert_eq!(bar2.y(), 12); + assert_eq!(bar2.v(), 31); + + let foo: &dyn Foo = baz; + let _: &dyn std::fmt::Debug = foo; + let _: &(dyn Send + Sync) = foo; + let _: &dyn Send = foo; + let _: &dyn Sync = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + + let foo: &dyn Foo = bar1; + let _: &dyn std::fmt::Debug = foo; + let _: &(dyn Send + Sync) = foo; + let _: &dyn Send = foo; + let _: &dyn Sync = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + + let foo: &dyn Foo = bar2; + let _: &dyn std::fmt::Debug = foo; + let _: &(dyn Send + Sync) = foo; + let _: &dyn Send = foo; + let _: &dyn Sync = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); +} diff --git a/src/test/ui/traits/trait-upcasting/invalid-upcast.rs b/src/test/ui/traits/trait-upcasting/invalid-upcast.rs new file mode 100644 index 0000000000000..ac1ef6313fc2d --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/invalid-upcast.rs @@ -0,0 +1,68 @@ +#![feature(trait_upcasting)] + +trait Foo { + fn a(&self) -> i32 { 10 } + + fn z(&self) -> i32 { 11 } + + fn y(&self) -> i32 { 12 } +} + +trait Bar { + fn b(&self) -> i32 { 20 } + + fn w(&self) -> i32 { 21 } +} + +trait Baz { + fn c(&self) -> i32 { 30 } +} + +impl Foo for i32 { + fn a(&self) -> i32 { 100 } +} + +impl Bar for i32 { + fn b(&self) -> i32 { 200 } +} + +impl Baz for i32 { + fn c(&self) -> i32 { 300 } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + //~^ ERROR `dyn Baz` doesn't implement `std::fmt::Debug` [E0277] + let _: &dyn Send = baz; + //~^ ERROR `dyn Baz` cannot be sent between threads safely [E0277] + let _: &dyn Sync = baz; + //~^ ERROR `dyn Baz` cannot be shared between threads safely [E0277] + + let bar: &dyn Bar = baz; + //~^ ERROR the trait bound `dyn Baz: Bar` is not satisfied [E0277] + let _: &dyn std::fmt::Debug = bar; + //~^ ERROR `dyn Bar` doesn't implement `std::fmt::Debug` [E0277] + let _: &dyn Send = bar; + //~^ ERROR `dyn Bar` cannot be sent between threads safely [E0277] + let _: &dyn Sync = bar; + //~^ ERROR `dyn Bar` cannot be shared between threads safely [E0277] + + let foo: &dyn Foo = baz; + //~^ ERROR the trait bound `dyn Baz: Foo` is not satisfied [E0277] + let _: &dyn std::fmt::Debug = foo; + //~^ ERROR `dyn Foo` doesn't implement `std::fmt::Debug` [E0277] + let _: &dyn Send = foo; + //~^ ERROR `dyn Foo` cannot be sent between threads safely [E0277] + let _: &dyn Sync = foo; + //~^ ERROR `dyn Foo` cannot be shared between threads safely [E0277] + + let foo: &dyn Foo = bar; + //~^ ERROR the trait bound `dyn Bar: Foo` is not satisfied [E0277] + let _: &dyn std::fmt::Debug = foo; + //~^ ERROR `dyn Foo` doesn't implement `std::fmt::Debug` [E0277] + let _: &dyn Send = foo; + //~^ ERROR `dyn Foo` cannot be sent between threads safely [E0277] + let _: &dyn Sync = foo; + //~^ ERROR `dyn Foo` cannot be shared between threads safely [E0277] +} diff --git a/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr b/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr new file mode 100644 index 0000000000000..731394d480aaa --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr @@ -0,0 +1,135 @@ +error[E0277]: `dyn Baz` doesn't implement `std::fmt::Debug` + --> $DIR/invalid-upcast.rs:35:35 + | +LL | let _: &dyn std::fmt::Debug = baz; + | ^^^ `dyn Baz` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `dyn Baz` + = note: required for the cast to the object type `dyn std::fmt::Debug` + +error[E0277]: `dyn Baz` cannot be sent between threads safely + --> $DIR/invalid-upcast.rs:37:24 + | +LL | let _: &dyn Send = baz; + | ^^^ `dyn Baz` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `dyn Baz` + = note: required for the cast to the object type `dyn std::marker::Send` + +error[E0277]: `dyn Baz` cannot be shared between threads safely + --> $DIR/invalid-upcast.rs:39:24 + | +LL | let _: &dyn Sync = baz; + | ^^^ `dyn Baz` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `dyn Baz` + = note: required for the cast to the object type `dyn std::marker::Sync` + +error[E0277]: the trait bound `dyn Baz: Bar` is not satisfied + --> $DIR/invalid-upcast.rs:42:25 + | +LL | let bar: &dyn Bar = baz; + | ^^^ the trait `Bar` is not implemented for `dyn Baz` + | + = note: required for the cast to the object type `dyn Bar` + +error[E0277]: `dyn Bar` doesn't implement `std::fmt::Debug` + --> $DIR/invalid-upcast.rs:44:35 + | +LL | let _: &dyn std::fmt::Debug = bar; + | ^^^ `dyn Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `dyn Bar` + = note: required for the cast to the object type `dyn std::fmt::Debug` + +error[E0277]: `dyn Bar` cannot be sent between threads safely + --> $DIR/invalid-upcast.rs:46:24 + | +LL | let _: &dyn Send = bar; + | ^^^ `dyn Bar` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `dyn Bar` + = note: required for the cast to the object type `dyn std::marker::Send` + +error[E0277]: `dyn Bar` cannot be shared between threads safely + --> $DIR/invalid-upcast.rs:48:24 + | +LL | let _: &dyn Sync = bar; + | ^^^ `dyn Bar` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `dyn Bar` + = note: required for the cast to the object type `dyn std::marker::Sync` + +error[E0277]: the trait bound `dyn Baz: Foo` is not satisfied + --> $DIR/invalid-upcast.rs:51:25 + | +LL | let foo: &dyn Foo = baz; + | ^^^ the trait `Foo` is not implemented for `dyn Baz` + | + = note: required for the cast to the object type `dyn Foo` + +error[E0277]: `dyn Foo` doesn't implement `std::fmt::Debug` + --> $DIR/invalid-upcast.rs:53:35 + | +LL | let _: &dyn std::fmt::Debug = foo; + | ^^^ `dyn Foo` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `dyn Foo` + = note: required for the cast to the object type `dyn std::fmt::Debug` + +error[E0277]: `dyn Foo` cannot be sent between threads safely + --> $DIR/invalid-upcast.rs:55:24 + | +LL | let _: &dyn Send = foo; + | ^^^ `dyn Foo` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `dyn Foo` + = note: required for the cast to the object type `dyn std::marker::Send` + +error[E0277]: `dyn Foo` cannot be shared between threads safely + --> $DIR/invalid-upcast.rs:57:24 + | +LL | let _: &dyn Sync = foo; + | ^^^ `dyn Foo` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `dyn Foo` + = note: required for the cast to the object type `dyn std::marker::Sync` + +error[E0277]: the trait bound `dyn Bar: Foo` is not satisfied + --> $DIR/invalid-upcast.rs:60:25 + | +LL | let foo: &dyn Foo = bar; + | ^^^ the trait `Foo` is not implemented for `dyn Bar` + | + = note: required for the cast to the object type `dyn Foo` + +error[E0277]: `dyn Foo` doesn't implement `std::fmt::Debug` + --> $DIR/invalid-upcast.rs:62:35 + | +LL | let _: &dyn std::fmt::Debug = foo; + | ^^^ `dyn Foo` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `dyn Foo` + = note: required for the cast to the object type `dyn std::fmt::Debug` + +error[E0277]: `dyn Foo` cannot be sent between threads safely + --> $DIR/invalid-upcast.rs:64:24 + | +LL | let _: &dyn Send = foo; + | ^^^ `dyn Foo` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `dyn Foo` + = note: required for the cast to the object type `dyn std::marker::Send` + +error[E0277]: `dyn Foo` cannot be shared between threads safely + --> $DIR/invalid-upcast.rs:66:24 + | +LL | let _: &dyn Sync = foo; + | ^^^ `dyn Foo` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `dyn Foo` + = note: required for the cast to the object type `dyn std::marker::Sync` + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-11515.rs b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs similarity index 67% rename from src/test/ui/issues/issue-11515.rs rename to src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs index a7671b9282a99..803b7a0b42392 100644 --- a/src/test/ui/issues/issue-11515.rs +++ b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs @@ -6,5 +6,6 @@ struct Test { fn main() { let closure: Box = Box::new(|| ()); - let test = box Test { func: closure }; //~ ERROR mismatched types + let test = box Test { func: closure }; + //~^ ERROR mismatched types } diff --git a/src/test/ui/issues/issue-11515.stderr b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.stderr similarity index 76% rename from src/test/ui/issues/issue-11515.stderr rename to src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.stderr index b53563d7b653c..d5a6768bee784 100644 --- a/src/test/ui/issues/issue-11515.stderr +++ b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.stderr @@ -1,11 +1,12 @@ error[E0308]: mismatched types - --> $DIR/issue-11515.rs:9:33 + --> $DIR/issue-11515-upcast-fn_mut-fn.rs:9:33 | LL | let test = box Test { func: closure }; | ^^^^^^^ expected trait `std::ops::FnMut`, found trait `std::ops::Fn` | = note: expected struct `std::boxed::Box<(dyn std::ops::FnMut() + 'static)>` found struct `std::boxed::Box<(dyn std::ops::Fn() + 'static)>` + = note: add `#![feature(trait_upcasting)]` to the crate attributes to enable trait upcasting error: aborting due to previous error diff --git a/src/test/ui/traits/trait-upcasting/lifetime.rs b/src/test/ui/traits/trait-upcasting/lifetime.rs new file mode 100644 index 0000000000000..46b461583db48 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/lifetime.rs @@ -0,0 +1,70 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { 10 } + + fn z(&self) -> i32 { 11 } + + fn y(&self) -> i32 { 12 } +} + +trait Bar: Foo { + fn b(&self) -> i32 { 20 } + + fn w(&self) -> i32 { 21 } +} + +trait Baz: Bar { + fn c(&self) -> i32 { 30 } +} + +impl Foo for i32 { + fn a(&self) -> i32 { 100 } +} + +impl Bar for i32 { + fn b(&self) -> i32 { 200 } +} + +impl Baz for i32 { + fn c(&self) -> i32 { 300 } +} + +// Note: upcast lifetime means a shorter lifetime. +fn upcast_baz<'a: 'b, 'b, T>(v: Box, _l: &'b T) -> Box { v } +fn upcast_bar<'a: 'b, 'b, T>(v: Box, _l: &'b T) -> Box { v } +fn upcast_foo<'a: 'b, 'b, T>(v: Box, _l: &'b T) -> Box { v } + +fn main() { + let v = Box::new(1); + let l = &(); // dummy lifetime (shorter than `baz`) + + let baz: Box = v.clone(); + let u = upcast_baz(baz, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + assert_eq!(u.c(), 300); + + let baz: Box = v.clone(); + let bar: Box = baz; + let u = upcast_bar(bar, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + + let baz: Box = v.clone(); + let foo: Box = baz; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + + let baz: Box = v.clone(); + let bar: Box = baz; + let foo: Box = bar; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); +} diff --git a/src/test/ui/traits/trait-upcasting/struct.rs b/src/test/ui/traits/trait-upcasting/struct.rs new file mode 100644 index 0000000000000..cf71ed4955137 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/struct.rs @@ -0,0 +1,155 @@ +// run-pass + +#![feature(trait_upcasting)] + +use std::rc::Rc; +use std::sync::Arc; + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { 10 } + + fn z(&self) -> i32 { 11 } + + fn y(&self) -> i32 { 12 } +} + +trait Bar: Foo { + fn b(&self) -> i32 { 20 } + + fn w(&self) -> i32 { 21 } +} + +trait Baz: Bar { + fn c(&self) -> i32 { 30 } +} + +impl Foo for i32 { + fn a(&self) -> i32 { 100 } +} + +impl Bar for i32 { + fn b(&self) -> i32 { 200 } +} + +impl Baz for i32 { + fn c(&self) -> i32 { 300 } +} + +fn test_box() { + let v = Box::new(1); + + let baz: Box = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Box = v.clone(); + let bar: Box = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Box = v.clone(); + let foo: Box = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Box = v.clone(); + let bar: Box = baz; + let foo: Box = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn test_rc() { + let v = Rc::new(1); + + let baz: Rc = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Rc = v.clone(); + let bar: Rc = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Rc = v.clone(); + let foo: Rc = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Rc = v.clone(); + let bar: Rc = baz; + let foo: Rc = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn test_arc() { + let v = Arc::new(1); + + let baz: Arc = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Arc = v.clone(); + let bar: Arc = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Arc = v.clone(); + let foo: Arc = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Arc = v.clone(); + let bar: Arc = baz; + let foo: Arc = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn main() { + test_box(); + test_rc(); + test_arc(); +} diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.rs b/src/test/ui/traits/trait-upcasting/subtrait-method.rs new file mode 100644 index 0000000000000..0c3af54fe2b04 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/subtrait-method.rs @@ -0,0 +1,51 @@ +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { 10 } + + fn z(&self) -> i32 { 11 } + + fn y(&self) -> i32 { 12 } +} + +trait Bar: Foo { + fn b(&self) -> i32 { 20 } + + fn w(&self) -> i32 { 21 } +} + +trait Baz: Bar { + fn c(&self) -> i32 { 30 } +} + +impl Foo for i32 { + fn a(&self) -> i32 { 100 } +} + +impl Bar for i32 { + fn b(&self) -> i32 { 200 } +} + +impl Baz for i32 { + fn c(&self) -> i32 { 300 } +} + +fn main() { + let baz: &dyn Baz = &1; + + let bar: &dyn Bar = baz; + bar.c(); + //~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599] + + let foo: &dyn Foo = baz; + foo.b(); + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + foo.c(); + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] + + let foo: &dyn Foo = bar; + foo.b(); + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + foo.c(); + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] +} diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.stderr b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr new file mode 100644 index 0000000000000..4b0765cdb8235 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr @@ -0,0 +1,68 @@ +error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope + --> $DIR/subtrait-method.rs:37:9 + | +LL | bar.c(); + | ^ help: there is an associated function with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:41:9 + | +LL | foo.b(); + | ^ help: there is an associated function with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `b`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:11:1 + | +LL | trait Bar: Foo { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:43:9 + | +LL | foo.c(); + | ^ help: there is an associated function with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:47:9 + | +LL | foo.b(); + | ^ help: there is an associated function with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `b`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:11:1 + | +LL | trait Bar: Foo { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:49:9 + | +LL | foo.c(); + | ^ help: there is an associated function with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/traits/trait-upcasting/upcast-fn_mut-fn-pass.rs b/src/test/ui/traits/trait-upcasting/upcast-fn_mut-fn-pass.rs new file mode 100644 index 0000000000000..d3f4b73e7e216 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/upcast-fn_mut-fn-pass.rs @@ -0,0 +1,12 @@ +// run-pass + +#![feature(trait_upcasting)] + +fn call_it(f: Box T>) -> T { + f() +} + +fn main() { + let f: Box i32> = Box::new(|| 42); + assert_eq!(call_it(f), 42); +}