summaryrefslogtreecommitdiffstats
path: root/src/test/ui/traits/trait-upcasting
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/traits/trait-upcasting')
-rw-r--r--src/test/ui/traits/trait-upcasting/basic.rs87
-rw-r--r--src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs39
-rw-r--r--src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs13
-rw-r--r--src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr21
-rw-r--r--src/test/ui/traits/trait-upcasting/diamond.rs115
-rw-r--r--src/test/ui/traits/trait-upcasting/invalid-upcast.rs87
-rw-r--r--src/test/ui/traits/trait-upcasting/invalid-upcast.stderr168
-rw-r--r--src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs13
-rw-r--r--src/test/ui/traits/trait-upcasting/lifetime.rs95
-rw-r--r--src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs25
-rw-r--r--src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr16
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs22
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr14
-rw-r--r--src/test/ui/traits/trait-upcasting/replace-vptr.rs49
-rw-r--r--src/test/ui/traits/trait-upcasting/struct.rs174
-rw-r--r--src/test/ui/traits/trait-upcasting/subtrait-method.rs70
-rw-r--r--src/test/ui/traits/trait-upcasting/subtrait-method.stderr68
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-1.rs27
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr23
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-2.rs32
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr42
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr22
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-3.rs21
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr18
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr33
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-4.rs49
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr52
27 files changed, 1395 insertions, 0 deletions
diff --git a/src/test/ui/traits/trait-upcasting/basic.rs b/src/test/ui/traits/trait-upcasting/basic.rs
new file mode 100644
index 000000000..484a222bc
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/basic.rs
@@ -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);
+}
diff --git a/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
new file mode 100644
index 000000000..8d0a9ef0a
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
@@ -0,0 +1,39 @@
+// run-pass
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
new file mode 100644
index 000000000..511e41562
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
@@ -0,0 +1,13 @@
+trait A: B + A {}
+//~^ ERROR cycle detected when computing the 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/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
new file mode 100644
index 000000000..15faab16a
--- /dev/null
+++ b/src/test/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/src/test/ui/traits/trait-upcasting/diamond.rs b/src/test/ui/traits/trait-upcasting/diamond.rs
new file mode 100644
index 000000000..e4e23c1a2
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/diamond.rs
@@ -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);
+}
diff --git a/src/test/ui/traits/trait-upcasting/invalid-upcast.rs b/src/test/ui/traits/trait-upcasting/invalid-upcast.rs
new file mode 100644
index 000000000..240224504
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/invalid-upcast.rs
@@ -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]
+}
diff --git a/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr b/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr
new file mode 100644
index 000000000..b4530ed0c
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/invalid-upcast.stderr
@@ -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`.
diff --git a/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
new file mode 100644
index 000000000..6d8800254
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
@@ -0,0 +1,13 @@
+// run-pass
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/lifetime.rs b/src/test/ui/traits/trait-upcasting/lifetime.rs
new file mode 100644
index 000000000..f029a6f08
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/lifetime.rs
@@ -0,0 +1,95 @@
+// 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
+ }
+}
+
+// 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/migrate-lint-deny.rs b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
new file mode 100644
index 000000000..c67251018
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
@@ -0,0 +1,25 @@
+#![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 {
+ type Target = dyn A;
+ fn deref(&self) -> &Self::Target {
+ todo!()
+ }
+}
+
+fn take_a(_: &dyn A) {}
+
+fn whoops(b: &dyn B) {
+ take_a(b)
+ //~^ ERROR `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output
+ //~^^ WARN this was previously accepted by the compiler but is being phased out;
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
new file mode 100644
index 000000000..35af9112a
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
@@ -0,0 +1,16 @@
+error: `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output
+ --> $DIR/migrate-lint-deny.rs:20:12
+ |
+LL | take_a(b)
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/migrate-lint-deny.rs:1:9
+ |
+LL | #![deny(deref_into_dyn_supertrait)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ = 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>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs b/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs
new file mode 100644
index 000000000..6986ad621
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs
@@ -0,0 +1,22 @@
+// check-fail
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr b/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr
new file mode 100644
index 000000000..e9670ad7d
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/multiple-occurence-ambiguousity.rs:21: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/src/test/ui/traits/trait-upcasting/replace-vptr.rs b/src/test/ui/traits/trait-upcasting/replace-vptr.rs
new file mode 100644
index 000000000..1164e4361
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/replace-vptr.rs
@@ -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);
+}
diff --git a/src/test/ui/traits/trait-upcasting/struct.rs b/src/test/ui/traits/trait-upcasting/struct.rs
new file mode 100644
index 000000000..0f3cb285b
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/struct.rs
@@ -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();
+}
diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.rs b/src/test/ui/traits/trait-upcasting/subtrait-method.rs
new file mode 100644
index 000000000..3508e1528
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/subtrait-method.rs
@@ -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]
+}
diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.stderr b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr
new file mode 100644
index 000000000..8c6901180
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr
@@ -0,0 +1,68 @@
+error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
+ --> $DIR/subtrait-method.rs: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`.
diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs
new file mode 100644
index 000000000..79ddedd41
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -0,0 +1,27 @@
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr
new file mode 100644
index 000000000..398537211
--- /dev/null
+++ b/src/test/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:17: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:17: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/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs
new file mode 100644
index 000000000..32754c538
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -0,0 +1,32 @@
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr
new file mode 100644
index 000000000..93c71f54e
--- /dev/null
+++ b/src/test/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:20: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:20: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:26: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:26: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/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr
new file mode 100644
index 000000000..e48ba709a
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr
@@ -0,0 +1,22 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:13: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`
+ |
+ = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:18: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`
+ |
+ = help: consider replacing `'a` with `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs
new file mode 100644
index 000000000..b3aa2279a
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-3.rs
@@ -0,0 +1,21 @@
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr
new file mode 100644
index 000000000..5ad151b50
--- /dev/null
+++ b/src/test/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:12: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:17: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/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr
new file mode 100644
index 000000000..a3411f40a
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr
@@ -0,0 +1,33 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:17: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`
+ |
+ = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:22: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`
+ |
+ = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:29:5
+ |
+LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+...
+LL | y.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+ |
+ = help: consider replacing `'a` with `'static`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs
new file mode 100644
index 000000000..70ccc87fc
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -0,0 +1,49 @@
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+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/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr
new file mode 100644
index 000000000..436129d0b
--- /dev/null
+++ b/src/test/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:16: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:21: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:27: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:32: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:37: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:45: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
+