about summary refs log tree commit diff
path: root/tests/ui/traits/trait-upcasting
diff options
context:
space:
mode:
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 00000000000..570ec5160bf
--- /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 00000000000..eae5cf8d58d
--- /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 00000000000..511e41562b2
--- /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 00000000000..15faab16abe
--- /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 00000000000..a4f81c464b4
--- /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 00000000000..e634bbd5ac6
--- /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 00000000000..3aa21ee3ddd
--- /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 00000000000..b672963ae98
--- /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 00000000000..9825158c2dd
--- /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 00000000000..d624187561e
--- /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 00000000000..4533b116342
--- /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 00000000000..2e53a00a90e
--- /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 00000000000..0ad18be03cd
--- /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 00000000000..9ccfc9306ac
--- /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 00000000000..a3e41696956
--- /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 00000000000..136d15af0e8
--- /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 00000000000..918159e845b
--- /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 00000000000..6bc9f4a75d3
--- /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 00000000000..fe269d8e99b
--- /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 00000000000..36b11dffdb1
--- /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 00000000000..ef007d5cb90
--- /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 00000000000..e6cb6a75399
--- /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 00000000000..b2db3a12797
--- /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 00000000000..e6cb6a75399
--- /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 00000000000..8d506e5807e
--- /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 00000000000..f40c48f0d12
--- /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 00000000000..8d506e5807e
--- /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
+