diff options
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/basic.rs | 80 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr | 16 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/diamond.rs | 108 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/invalid-upcast.rs | 68 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/invalid-upcast.stderr | 135 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/lifetime.rs | 70 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/struct.rs | 155 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/subtrait-method.rs | 51 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-upcasting/subtrait-method.stderr | 68 |
10 files changed, 764 insertions, 0 deletions
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 00000000000..78ddbe08888 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/basic.rs @@ -0,0 +1,80 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + 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 00000000000..1666b7ba292 --- /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<dyn A> = Box::new(()); + let _b: Box<dyn B> = 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 00000000000..7a04c5d0dbb --- /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 00000000000..531b40d83f9 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/diamond.rs @@ -0,0 +1,108 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + 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 00000000000..ac1ef6313fc --- /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 00000000000..731394d480a --- /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/traits/trait-upcasting/lifetime.rs b/src/test/ui/traits/trait-upcasting/lifetime.rs new file mode 100644 index 00000000000..46b461583db --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/lifetime.rs @@ -0,0 +1,70 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + 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<dyn Baz + 'a>, _l: &'b T) -> Box<dyn Baz + 'b> { v } +fn upcast_bar<'a: 'b, 'b, T>(v: Box<dyn Bar + 'a>, _l: &'b T) -> Box<dyn Bar + 'b> { v } +fn upcast_foo<'a: 'b, 'b, T>(v: Box<dyn Foo + 'a>, _l: &'b T) -> Box<dyn Foo + 'b> { v } + +fn main() { + let v = Box::new(1); + let l = &(); // dummy lifetime (shorter than `baz`) + + let baz: Box<dyn Baz> = 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<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + let u = upcast_bar(bar, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + + let baz: Box<dyn Baz> = v.clone(); + let foo: Box<dyn Foo> = baz; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + + let baz: Box<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + let foo: Box<dyn Foo> = 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 00000000000..cf71ed49551 --- /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<i32> + 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<dyn Baz> = 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<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = 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<dyn Baz> = v.clone(); + let foo: Box<dyn Foo> = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Box<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + let foo: Box<dyn Foo> = 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<dyn Baz> = 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<dyn Baz> = v.clone(); + let bar: Rc<dyn Bar> = 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<dyn Baz> = v.clone(); + let foo: Rc<dyn Foo> = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Rc<dyn Baz> = v.clone(); + let bar: Rc<dyn Bar> = baz; + let foo: Rc<dyn Foo> = 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<dyn Baz> = 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<dyn Baz> = v.clone(); + let bar: Arc<dyn Bar> = 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<dyn Baz> = v.clone(); + let foo: Arc<dyn Foo> = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Arc<dyn Baz> = v.clone(); + let bar: Arc<dyn Bar> = baz; + let foo: Arc<dyn Foo> = 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 00000000000..0c3af54fe2b --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/subtrait-method.rs @@ -0,0 +1,51 @@ +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + 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 00000000000..4b0765cdb82 --- /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`. |
