]> git.lizzy.rs Git - rust.git/commitdiff
Added tests.
authorAlexander Regueiro <alexreg@me.com>
Tue, 5 Nov 2019 02:18:39 +0000 (02:18 +0000)
committerCharles Lew <crlf0710@gmail.com>
Mon, 2 Aug 2021 17:09:38 +0000 (01:09 +0800)
src/test/ui/traits/trait-upcasting/basic.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/diamond.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/invalid-upcast.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/invalid-upcast.stderr [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/lifetime.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/struct.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/subtrait-method.rs [new file with mode: 0644]
src/test/ui/traits/trait-upcasting/subtrait-method.stderr [new file with mode: 0644]

diff --git a/src/test/ui/traits/trait-upcasting/basic.rs b/src/test/ui/traits/trait-upcasting/basic.rs
new file mode 100644 (file)
index 0000000..78ddbe0
--- /dev/null
@@ -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 (file)
index 0000000..1666b7b
--- /dev/null
@@ -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 (file)
index 0000000..7a04c5d
--- /dev/null
@@ -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 (file)
index 0000000..531b40d
--- /dev/null
@@ -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 (file)
index 0000000..ac1ef63
--- /dev/null
@@ -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 (file)
index 0000000..731394d
--- /dev/null
@@ -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 (file)
index 0000000..46b4615
--- /dev/null
@@ -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 (file)
index 0000000..cf71ed4
--- /dev/null
@@ -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 (file)
index 0000000..0c3af54
--- /dev/null
@@ -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 (file)
index 0000000..4b0765c
--- /dev/null
@@ -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`.