Auto merge of #87515 - crlf0710:trait_upcasting_part2, r=bjorn3
Trait upcasting coercion (part2) This is the second part of trait upcasting coercion implementation. Currently this is blocked on #86264 . The third part might be implemented using unsafety checking r? `@bjorn3`
This commit is contained in:
commit
c6bc102fea
22 changed files with 1186 additions and 93 deletions
87
src/test/ui/traits/trait-upcasting/basic.rs
Normal file
87
src/test/ui/traits/trait-upcasting/basic.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
assert_eq!(*foo, 1);
|
||||
assert_eq!(foo.a(), 100);
|
||||
assert_eq!(foo.z(), 11);
|
||||
assert_eq!(foo.y(), 12);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
trait A: B + A {}
|
||||
//~^ ERROR cycle detected when computing the super predicates 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
error[E0391]: cycle detected when computing the super predicates of `A`
|
||||
--> $DIR/cyclic-trait-resolution.rs:1:1
|
||||
|
|
||||
LL | trait A: B + A {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing the super traits of `A`...
|
||||
--> $DIR/cyclic-trait-resolution.rs:1:14
|
||||
|
|
||||
LL | trait A: B + A {}
|
||||
| ^
|
||||
= note: ...which again requires computing the super predicates 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`.
|
||||
115
src/test/ui/traits/trait-upcasting/diamond.rs
Normal file
115
src/test/ui/traits/trait-upcasting/diamond.rs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
assert_eq!(*foo, 1);
|
||||
assert_eq!(foo.a(), 100);
|
||||
|
||||
let foo: &dyn Foo = bar1;
|
||||
let _: &dyn std::fmt::Debug = foo;
|
||||
assert_eq!(*foo, 1);
|
||||
assert_eq!(foo.a(), 100);
|
||||
|
||||
let foo: &dyn Foo = bar2;
|
||||
let _: &dyn std::fmt::Debug = foo;
|
||||
assert_eq!(*foo, 1);
|
||||
assert_eq!(foo.a(), 100);
|
||||
}
|
||||
87
src/test/ui/traits/trait-upcasting/invalid-upcast.rs
Normal file
87
src/test/ui/traits/trait-upcasting/invalid-upcast.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
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 mismatched types [E0308]
|
||||
let _: &dyn Send = baz;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Sync = baz;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
|
||||
let bar: &dyn Bar = baz;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn std::fmt::Debug = bar;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Send = bar;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Sync = bar;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
|
||||
let foo: &dyn Foo = baz;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn std::fmt::Debug = foo;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Send = foo;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Sync = foo;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
|
||||
let foo: &dyn Foo = bar;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn std::fmt::Debug = foo;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Send = foo;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
let _: &dyn Sync = foo;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
}
|
||||
168
src/test/ui/traits/trait-upcasting/invalid-upcast.stderr
Normal file
168
src/test/ui/traits/trait-upcasting/invalid-upcast.stderr
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:54:35
|
||||
|
|
||||
LL | let _: &dyn std::fmt::Debug = baz;
|
||||
| -------------------- ^^^ expected trait `Debug`, found trait `Baz`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Debug`
|
||||
found reference `&dyn Baz`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:56:24
|
||||
|
|
||||
LL | let _: &dyn Send = baz;
|
||||
| --------- ^^^ expected trait `Send`, found trait `Baz`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Send`
|
||||
found reference `&dyn Baz`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:58:24
|
||||
|
|
||||
LL | let _: &dyn Sync = baz;
|
||||
| --------- ^^^ expected trait `Sync`, found trait `Baz`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Sync`
|
||||
found reference `&dyn Baz`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:61:25
|
||||
|
|
||||
LL | let bar: &dyn Bar = baz;
|
||||
| -------- ^^^ expected trait `Bar`, found trait `Baz`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Bar`
|
||||
found reference `&dyn Baz`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:63:35
|
||||
|
|
||||
LL | let _: &dyn std::fmt::Debug = bar;
|
||||
| -------------------- ^^^ expected trait `Debug`, found trait `Bar`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Debug`
|
||||
found reference `&dyn Bar`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:65:24
|
||||
|
|
||||
LL | let _: &dyn Send = bar;
|
||||
| --------- ^^^ expected trait `Send`, found trait `Bar`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Send`
|
||||
found reference `&dyn Bar`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:67:24
|
||||
|
|
||||
LL | let _: &dyn Sync = bar;
|
||||
| --------- ^^^ expected trait `Sync`, found trait `Bar`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Sync`
|
||||
found reference `&dyn Bar`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:70:25
|
||||
|
|
||||
LL | let foo: &dyn Foo = baz;
|
||||
| -------- ^^^ expected trait `Foo`, found trait `Baz`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Foo`
|
||||
found reference `&dyn Baz`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:72:35
|
||||
|
|
||||
LL | let _: &dyn std::fmt::Debug = foo;
|
||||
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Debug`
|
||||
found reference `&dyn Foo`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:74:24
|
||||
|
|
||||
LL | let _: &dyn Send = foo;
|
||||
| --------- ^^^ expected trait `Send`, found trait `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Send`
|
||||
found reference `&dyn Foo`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:76:24
|
||||
|
|
||||
LL | let _: &dyn Sync = foo;
|
||||
| --------- ^^^ expected trait `Sync`, found trait `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Sync`
|
||||
found reference `&dyn Foo`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:79:25
|
||||
|
|
||||
LL | let foo: &dyn Foo = bar;
|
||||
| -------- ^^^ expected trait `Foo`, found trait `Bar`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Foo`
|
||||
found reference `&dyn Bar`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:81:35
|
||||
|
|
||||
LL | let _: &dyn std::fmt::Debug = foo;
|
||||
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Debug`
|
||||
found reference `&dyn Foo`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:83:24
|
||||
|
|
||||
LL | let _: &dyn Send = foo;
|
||||
| --------- ^^^ expected trait `Send`, found trait `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Send`
|
||||
found reference `&dyn Foo`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid-upcast.rs:85:24
|
||||
|
|
||||
LL | let _: &dyn Sync = foo;
|
||||
| --------- ^^^ expected trait `Sync`, found trait `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&dyn Sync`
|
||||
found reference `&dyn Foo`
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
96
src/test/ui/traits/trait-upcasting/lifetime.rs
Normal file
96
src/test/ui/traits/trait-upcasting/lifetime.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// run-pass
|
||||
// ignore-compare-mode-nll
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
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);
|
||||
}
|
||||
49
src/test/ui/traits/trait-upcasting/replace-vptr.rs
Normal file
49
src/test/ui/traits/trait-upcasting/replace-vptr.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait A {
|
||||
fn foo_a(&self);
|
||||
}
|
||||
|
||||
trait B {
|
||||
fn foo_b(&self);
|
||||
}
|
||||
|
||||
trait C: A + B {
|
||||
fn foo_c(&self);
|
||||
}
|
||||
|
||||
struct S(i32);
|
||||
|
||||
impl A for S {
|
||||
fn foo_a(&self) {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
impl B for S {
|
||||
fn foo_b(&self) {
|
||||
assert_eq!(42, self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl C for S {
|
||||
fn foo_c(&self) {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
fn invoke_inner(b: &dyn B) {
|
||||
b.foo_b();
|
||||
}
|
||||
|
||||
fn invoke_outer(c: &dyn C) {
|
||||
invoke_inner(c);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = S(42);
|
||||
invoke_outer(&s);
|
||||
}
|
||||
174
src/test/ui/traits/trait-upcasting/struct.rs
Normal file
174
src/test/ui/traits/trait-upcasting/struct.rs
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
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();
|
||||
}
|
||||
70
src/test/ui/traits/trait-upcasting/subtrait-method.rs
Normal file
70
src/test/ui/traits/trait-upcasting/subtrait-method.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#![feature(trait_upcasting)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
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]
|
||||
}
|
||||
68
src/test/ui/traits/trait-upcasting/subtrait-method.stderr
Normal file
68
src/test/ui/traits/trait-upcasting/subtrait-method.stderr
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
|
||||
--> $DIR/subtrait-method.rs:56: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:28:1
|
||||
|
|
||||
LL | trait Baz: Bar {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
|
||||
--> $DIR/subtrait-method.rs:60: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:18:1
|
||||
|
|
||||
LL | trait Bar: Foo {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
|
||||
--> $DIR/subtrait-method.rs:62: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:28:1
|
||||
|
|
||||
LL | trait Baz: Bar {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
|
||||
--> $DIR/subtrait-method.rs:66: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:18:1
|
||||
|
|
||||
LL | trait Bar: Foo {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
|
||||
--> $DIR/subtrait-method.rs:68: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:28:1
|
||||
|
|
||||
LL | trait Baz: Bar {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue