summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/trait-upcasting
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/traits/trait-upcasting
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/traits/trait-upcasting')
-rw-r--r--tests/ui/traits/trait-upcasting/basic.rs86
-rw-r--r--tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs38
-rw-r--r--tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs13
-rw-r--r--tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr21
-rw-r--r--tests/ui/traits/trait-upcasting/diamond.rs114
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.rs86
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.stderr168
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs12
-rw-r--r--tests/ui/traits/trait-upcasting/lifetime.rs94
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.rs27
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr19
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs21
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/replace-vptr.rs48
-rw-r--r--tests/ui/traits/trait-upcasting/struct.rs173
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.rs69
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.stderr68
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs26
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.stderr23
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs31
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr42
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr18
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.rs20
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.stderr18
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr52
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.rs48
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr52
27 files changed, 1401 insertions, 0 deletions
diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs
new file mode 100644
index 000000000..570ec5160
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/basic.rs
@@ -0,0 +1,86 @@
+// 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;
+ 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);
+}
diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
new file mode 100644
index 000000000..eae5cf8d5
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
@@ -0,0 +1,38 @@
+// run-pass
+#![feature(trait_upcasting)]
+
+trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
+trait Bar<T: Default + ToString> {
+ fn bar(&self) -> String {
+ T::default().to_string()
+ }
+}
+
+struct S1;
+
+impl Bar<i32> for S1 {}
+impl Foo<i32> for S1 {}
+
+struct S2;
+impl Bar<i32> for S2 {}
+impl Bar<bool> for S2 {}
+impl Foo<bool> for S2 {}
+
+fn test1(x: &dyn Foo<i32>) {
+ let s = x as &dyn Bar<i32>;
+ assert_eq!("0", &s.bar().to_string());
+}
+
+fn test2(x: &dyn Foo<bool>) {
+ let p = x as &dyn Bar<i32>;
+ assert_eq!("0", &p.bar().to_string());
+ let q = x as &dyn Bar<bool>;
+ assert_eq!("false", &q.bar().to_string());
+}
+
+fn main() {
+ let s1 = S1;
+ test1(&s1);
+ let s2 = S2;
+ test2(&s2);
+}
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
new file mode 100644
index 000000000..511e41562
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
@@ -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;
+}
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
new file mode 100644
index 000000000..15faab16a
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
@@ -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`.
diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs
new file mode 100644
index 000000000..a4f81c464
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/diamond.rs
@@ -0,0 +1,114 @@
+// 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;
+ 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);
+}
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
new file mode 100644
index 000000000..e634bbd5a
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
@@ -0,0 +1,86 @@
+#![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 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]
+}
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
new file mode 100644
index 000000000..3aa21ee3d
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
@@ -0,0 +1,168 @@
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:53: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:55: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:57: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:60: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:62: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:64: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:66: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:69: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:71: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:73: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:75: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:78: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:80: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:82: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:84: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`.
diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
new file mode 100644
index 000000000..b672963ae
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
@@ -0,0 +1,12 @@
+// run-pass
+#![feature(trait_upcasting)]
+
+struct Test {
+ func: Box<dyn FnMut() + 'static>,
+}
+
+fn main() {
+ let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
+ let mut test = Box::new(Test { func: closure });
+ (test.func)();
+}
diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs
new file mode 100644
index 000000000..9825158c2
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/lifetime.rs
@@ -0,0 +1,94 @@
+// 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/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
new file mode 100644
index 000000000..d62418756
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
@@ -0,0 +1,27 @@
+#![deny(deref_into_dyn_supertrait)]
+
+extern crate core;
+
+use core::ops::Deref;
+
+// issue 89190
+trait A {}
+trait B: A {}
+
+impl<'a> Deref for dyn 'a + B {
+ //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
+ //~| WARN this was previously accepted by the compiler but is being phased out;
+
+ type Target = dyn A;
+ fn deref(&self) -> &Self::Target {
+ todo!()
+ }
+}
+
+fn take_a(_: &dyn A) {}
+
+fn whoops(b: &dyn B) {
+ take_a(b)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
new file mode 100644
index 000000000..4533b1163
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
@@ -0,0 +1,19 @@
+error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
+ --> $DIR/migrate-lint-deny.rs:11:1
+ |
+LL | impl<'a> Deref for dyn 'a + B {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | type Target = dyn A;
+ | -------------------- target type is set here
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
+note: the lint level is defined here
+ --> $DIR/migrate-lint-deny.rs:1:9
+ |
+LL | #![deny(deref_into_dyn_supertrait)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
new file mode 100644
index 000000000..2e53a00a9
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
@@ -0,0 +1,21 @@
+// check-fail
+#![feature(trait_upcasting)]
+
+trait Bar<T> {
+ fn bar(&self, _: T) {}
+}
+
+trait Foo: Bar<i32> + Bar<u32> {
+ fn foo(&self, _: ()) {}
+}
+
+struct S;
+
+impl Bar<i32> for S {}
+impl Bar<u32> for S {}
+impl Foo for S {}
+
+fn main() {
+ let s: &dyn Foo = &S;
+ let t: &dyn Bar<_> = s; //~ ERROR mismatched types
+}
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
new file mode 100644
index 000000000..0ad18be03
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/multiple-occurrence-ambiguousity.rs:20:26
+ |
+LL | let t: &dyn Bar<_> = s;
+ | ----------- ^ expected trait `Bar`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Bar<_>`
+ found reference `&dyn Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs
new file mode 100644
index 000000000..9ccfc9306
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+#![feature(trait_upcasting)]
+
+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);
+}
diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs
new file mode 100644
index 000000000..a3e416969
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/struct.rs
@@ -0,0 +1,173 @@
+// 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/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs
new file mode 100644
index 000000000..136d15af0
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs
@@ -0,0 +1,69 @@
+#![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/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
new file mode 100644
index 000000000..918159e84
--- /dev/null
+++ b/tests/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:55:9
+ |
+LL | bar.c();
+ | ^ help: there is a method 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:27:1
+ |
+LL | trait Baz: Bar {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:59:9
+ |
+LL | foo.b();
+ | ^ help: there is a method 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:17:1
+ |
+LL | trait Bar: Foo {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:61:9
+ |
+LL | foo.c();
+ | ^ help: there is a method 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:27:1
+ |
+LL | trait Baz: Bar {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:65:9
+ |
+LL | foo.b();
+ | ^ help: there is a method 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:17:1
+ |
+LL | trait Bar: Foo {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:67:9
+ |
+LL | foo.c();
+ | ^ help: there is a method 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:27: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/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
new file mode 100644
index 000000000..6bc9f4a75
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -0,0 +1,26 @@
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+trait Bar<T> {
+ fn bar(&self) -> Option<T> {
+ None
+ }
+}
+
+fn test_specific(x: &dyn Foo) {
+ let _ = x as &dyn Bar<i32>; // OK
+ let _ = x as &dyn Bar<u32>; // OK
+}
+
+fn test_unknown_version(x: &dyn Foo) {
+ let _ = x as &dyn Bar<_>; // Ambiguous
+ //~^ ERROR non-primitive cast
+ //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
+}
+
+fn test_infer_version(x: &dyn Foo) {
+ let a = x as &dyn Bar<_>; // OK
+ let _: Option<u32> = a.bar();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
new file mode 100644
index 000000000..fe269d8e9
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
@@ -0,0 +1,23 @@
+error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
+ --> $DIR/type-checking-test-1.rs:16:13
+ |
+LL | let _ = x as &dyn Bar<_>; // Ambiguous
+ | ^^^^^^^^^^^^^^^^ invalid cast
+ |
+help: consider borrowing the value
+ |
+LL | let _ = &x as &dyn Bar<_>; // Ambiguous
+ | +
+
+error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
+ --> $DIR/type-checking-test-1.rs:16:13
+ |
+LL | let _ = x as &dyn Bar<_>; // Ambiguous
+ | ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
+ |
+ = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0605.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
new file mode 100644
index 000000000..36b11dffd
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -0,0 +1,31 @@
+#![feature(trait_upcasting)]
+
+trait Foo<T>: Bar<i32> + Bar<T> {}
+trait Bar<T> {
+ fn bar(&self) -> Option<T> {
+ None
+ }
+}
+
+fn test_specific(x: &dyn Foo<i32>) {
+ let _ = x as &dyn Bar<i32>; // OK
+}
+
+fn test_specific2(x: &dyn Foo<u32>) {
+ let _ = x as &dyn Bar<i32>; // OK
+}
+
+fn test_specific3(x: &dyn Foo<i32>) {
+ let _ = x as &dyn Bar<u32>; // Error
+ //~^ ERROR non-primitive cast
+ //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
+}
+
+fn test_infer_arg(x: &dyn Foo<u32>) {
+ let a = x as &dyn Bar<_>; // Ambiguous
+ //~^ ERROR non-primitive cast
+ //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
+ let _ = a.bar();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
new file mode 100644
index 000000000..ef007d5cb
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -0,0 +1,42 @@
+error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
+ --> $DIR/type-checking-test-2.rs:19:13
+ |
+LL | let _ = x as &dyn Bar<u32>; // Error
+ | ^^^^^^^^^^^^^^^^^^ invalid cast
+ |
+help: consider borrowing the value
+ |
+LL | let _ = &x as &dyn Bar<u32>; // Error
+ | +
+
+error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
+ --> $DIR/type-checking-test-2.rs:19:13
+ |
+LL | let _ = x as &dyn Bar<u32>; // Error
+ | ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
+ |
+ = note: required for the cast from `&dyn Foo<i32>` to the object type `dyn Bar<u32>`
+
+error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
+ --> $DIR/type-checking-test-2.rs:25:13
+ |
+LL | let a = x as &dyn Bar<_>; // Ambiguous
+ | ^^^^^^^^^^^^^^^^ invalid cast
+ |
+help: consider borrowing the value
+ |
+LL | let a = &x as &dyn Bar<_>; // Ambiguous
+ | +
+
+error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
+ --> $DIR/type-checking-test-2.rs:25:13
+ |
+LL | let a = x as &dyn Bar<_>; // Ambiguous
+ | ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
+ |
+ = note: required for the cast from `&dyn Foo<u32>` to the object type `dyn Bar<_>`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0605.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr
new file mode 100644
index 000000000..e6cb6a753
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:11:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a>; // Error
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:16:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
new file mode 100644
index 000000000..b2db3a127
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
@@ -0,0 +1,20 @@
+#![feature(trait_upcasting)]
+
+trait Foo<'a>: Bar<'a> {}
+trait Bar<'a> {}
+
+fn test_correct(x: &dyn Foo<'static>) {
+ let _ = x as &dyn Bar<'static>;
+}
+
+fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ let _ = x as &dyn Bar<'a>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong2<'a>(x: &dyn Foo<'a>) {
+ let _ = x as &dyn Bar<'static>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
new file mode 100644
index 000000000..e6cb6a753
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:11:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a>; // Error
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:16:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr
new file mode 100644
index 000000000..8d506e580
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr
@@ -0,0 +1,52 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:15:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static, 'a>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:20:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a, 'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:26:5
+ |
+LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | let y = x as &dyn Bar<'_, '_>;
+LL | y.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:31:5
+ |
+LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:36:5
+ |
+LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:44:5
+ |
+LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+...
+LL | z.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
new file mode 100644
index 000000000..f40c48f0d
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -0,0 +1,48 @@
+#![feature(trait_upcasting)]
+
+trait Foo<'a>: Bar<'a, 'a> {}
+trait Bar<'a, 'b> {
+ fn get_b(&self) -> Option<&'a u32> {
+ None
+ }
+}
+
+fn test_correct(x: &dyn Foo<'static>) {
+ let _ = x as &dyn Bar<'static, 'static>;
+}
+
+fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ let _ = x as &dyn Bar<'static, 'a>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ let _ = x as &dyn Bar<'a, 'static>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ let y = x as &dyn Bar<'_, '_>;
+ y.get_b() // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ <_ as Bar>::get_b(x) // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ <_ as Bar<'_, '_>>::get_b(x) // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ let y = x as &dyn Bar<'_, '_>;
+ y.get_b(); // ERROR
+ let z = y;
+ z.get_b() // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
new file mode 100644
index 000000000..8d506e580
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -0,0 +1,52 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:15:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static, 'a>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:20:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a, 'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:26:5
+ |
+LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | let y = x as &dyn Bar<'_, '_>;
+LL | y.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:31:5
+ |
+LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:36:5
+ |
+LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:44:5
+ |
+LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+...
+LL | z.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 6 previous errors
+