about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-25 05:09:30 +0000
committerbors <bors@rust-lang.org>2024-06-25 05:09:30 +0000
commit164e1297e1bce47a241e4d93a9f044452b288715 (patch)
tree89d6725b38c02bd32b7b407ec422edded564be0e
parentfc555cd832ee743ff5410c35de2b0dd59ec4322e (diff)
parent45da03541c0a07f63f1b8c15cccd2fc8692cca7e (diff)
downloadrust-164e1297e1bce47a241e4d93a9f044452b288715.tar.gz
rust-164e1297e1bce47a241e4d93a9f044452b288715.zip
Auto merge of #125610 - oli-obk:define_opaque_types14, r=compiler-errors
Allow constraining opaque types during various unsizing casts

allows unsizing of tuples, arrays and Adts to constraint opaque types in their generic parameters to concrete types on either side of the unsizing cast.

Also allows constraining opaque types during trait object casts that only differ in auto traits or lifetimes.

cc #116652
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs8
-rw-r--r--tests/ui/impl-trait/trait_upcasting.rs26
-rw-r--r--tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs18
-rw-r--r--tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr9
-rw-r--r--tests/ui/impl-trait/unsize_adt.rs5
-rw-r--r--tests/ui/impl-trait/unsize_adt.stderr17
-rw-r--r--tests/ui/impl-trait/unsize_slice.rs5
-rw-r--r--tests/ui/impl-trait/unsize_slice.stderr17
-rw-r--r--tests/ui/impl-trait/unsize_tuple.rs5
-rw-r--r--tests/ui/impl-trait/unsize_tuple.stderr17
-rw-r--r--tests/ui/impl-trait/unsized_coercion.next.stderr26
-rw-r--r--tests/ui/impl-trait/unsized_coercion.rs21
-rw-r--r--tests/ui/impl-trait/unsized_coercion2.old.stderr12
-rw-r--r--tests/ui/impl-trait/unsized_coercion2.rs21
-rw-r--r--tests/ui/impl-trait/unsized_coercion3.next.stderr38
-rw-r--r--tests/ui/impl-trait/unsized_coercion3.old.stderr26
-rw-r--r--tests/ui/impl-trait/unsized_coercion3.rs24
-rw-r--r--tests/ui/impl-trait/unsized_coercion4.rs20
-rw-r--r--tests/ui/impl-trait/unsized_coercion5.next.stderr14
-rw-r--r--tests/ui/impl-trait/unsized_coercion5.old.stderr38
-rw-r--r--tests/ui/impl-trait/unsized_coercion5.rs24
21 files changed, 330 insertions, 61 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index b50f6260ab3..8c5dc88184c 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1162,7 +1162,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let InferOk { mut obligations, .. } = self
                     .infcx
                     .at(&obligation.cause, obligation.param_env)
-                    .sup(DefineOpaqueTypes::No, target, source_trait)
+                    .sup(DefineOpaqueTypes::Yes, target, source_trait)
                     .map_err(|_| Unimplemented)?;
 
                 // Register one obligation for 'a: 'b.
@@ -1229,7 +1229,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let InferOk { obligations, .. } = self
                     .infcx
                     .at(&obligation.cause, obligation.param_env)
-                    .eq(DefineOpaqueTypes::No, b, a)
+                    .eq(DefineOpaqueTypes::Yes, b, a)
                     .map_err(|_| Unimplemented)?;
 
                 ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
@@ -1277,7 +1277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let InferOk { obligations, .. } = self
                     .infcx
                     .at(&obligation.cause, obligation.param_env)
-                    .eq(DefineOpaqueTypes::No, target, new_struct)
+                    .eq(DefineOpaqueTypes::Yes, target, new_struct)
                     .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
@@ -1310,7 +1310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let InferOk { mut obligations, .. } = self
                     .infcx
                     .at(&obligation.cause, obligation.param_env)
-                    .eq(DefineOpaqueTypes::No, target, new_tuple)
+                    .eq(DefineOpaqueTypes::Yes, target, new_tuple)
                     .map_err(|_| Unimplemented)?;
 
                 // Add a nested `T: Unsize<U>` predicate.
diff --git a/tests/ui/impl-trait/trait_upcasting.rs b/tests/ui/impl-trait/trait_upcasting.rs
new file mode 100644
index 00000000000..ce811004fae
--- /dev/null
+++ b/tests/ui/impl-trait/trait_upcasting.rs
@@ -0,0 +1,26 @@
+//! Test that we allow unsizing `Trait<Concrete>` to `Trait<Opaque>` and vice versa
+
+//@ check-pass
+
+trait Trait<T> {}
+
+impl<T, U> Trait<T> for U {}
+
+fn hello() -> &'static (dyn Trait<impl Sized> + Send) {
+    if false {
+        let x = hello();
+        let _: &'static dyn Trait<()> = x;
+    }
+    todo!()
+}
+
+fn bye() -> &'static dyn Trait<impl Sized> {
+    if false {
+        let mut x = bye();
+        let y: &'static (dyn Trait<()> + Send) = &();
+        x = y;
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs
new file mode 100644
index 00000000000..bed88db1acc
--- /dev/null
+++ b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs
@@ -0,0 +1,18 @@
+//! Show an uninformative diagnostic that we could possibly improve in the future
+
+trait Trait<T> {}
+
+impl<T, U> Trait<T> for U {}
+
+fn hello() -> &'static (dyn Trait<impl Sized> + Send) {
+    //~^ ERROR: type annotations needed
+    if false {
+        let x = hello();
+        let _: &'static dyn Trait<()> = &x;
+        //^ Note the extra `&`, paired with the blanket impl causing
+        // `impl Sized` to never get a hidden type registered.
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr
new file mode 100644
index 00000000000..92da47b08e9
--- /dev/null
+++ b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/trait_upcasting_reference_mismatch.rs:7:35
+   |
+LL | fn hello() -> &'static (dyn Trait<impl Sized> + Send) {
+   |                                   ^^^^^^^^^^ cannot infer type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/unsize_adt.rs b/tests/ui/impl-trait/unsize_adt.rs
index fce5094bd40..825384b61e8 100644
--- a/tests/ui/impl-trait/unsize_adt.rs
+++ b/tests/ui/impl-trait/unsize_adt.rs
@@ -1,4 +1,6 @@
-//! Test that we do not allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`.
+//! Test that we allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`.
+
+//@check-pass
 
 struct Foo<T: ?Sized>(T);
 
@@ -6,7 +8,6 @@ fn hello() -> Foo<[impl Sized; 2]> {
     if false {
         let x = hello();
         let _: &Foo<[i32]> = &x;
-        //~^ ERROR: mismatched types
     }
     todo!()
 }
diff --git a/tests/ui/impl-trait/unsize_adt.stderr b/tests/ui/impl-trait/unsize_adt.stderr
deleted file mode 100644
index 2b93b4a571b..00000000000
--- a/tests/ui/impl-trait/unsize_adt.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/unsize_adt.rs:8:30
-   |
-LL | fn hello() -> Foo<[impl Sized; 2]> {
-   |                    ---------- the found opaque type
-...
-LL |         let _: &Foo<[i32]> = &x;
-   |                -----------   ^^ expected `&Foo<[i32]>`, found `&Foo<[impl Sized; 2]>`
-   |                |
-   |                expected due to this
-   |
-   = note: expected reference `&Foo<[i32]>`
-              found reference `&Foo<[impl Sized; 2]>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/unsize_slice.rs b/tests/ui/impl-trait/unsize_slice.rs
index ec0f1626564..b0cf1c7ca6d 100644
--- a/tests/ui/impl-trait/unsize_slice.rs
+++ b/tests/ui/impl-trait/unsize_slice.rs
@@ -1,10 +1,11 @@
-//! Test that we do not allow unsizing `[Opaque; N]` to `[Concrete]`.
+//! Test that we allow unsizing `[Opaque; N]` to `[Concrete]`.
+
+//@check-pass
 
 fn hello() -> [impl Sized; 2] {
     if false {
         let x = hello();
         let _: &[i32] = &x;
-        //~^ ERROR: mismatched types
     }
     todo!()
 }
diff --git a/tests/ui/impl-trait/unsize_slice.stderr b/tests/ui/impl-trait/unsize_slice.stderr
deleted file mode 100644
index 6a7fdb46163..00000000000
--- a/tests/ui/impl-trait/unsize_slice.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/unsize_slice.rs:6:25
-   |
-LL | fn hello() -> [impl Sized; 2] {
-   |                ---------- the found opaque type
-...
-LL |         let _: &[i32] = &x;
-   |                ------   ^^ expected `&[i32]`, found `&[impl Sized; 2]`
-   |                |
-   |                expected due to this
-   |
-   = note: expected reference `&[i32]`
-              found reference `&[impl Sized; 2]`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/unsize_tuple.rs b/tests/ui/impl-trait/unsize_tuple.rs
index 630b8fd430f..2678564f0e8 100644
--- a/tests/ui/impl-trait/unsize_tuple.rs
+++ b/tests/ui/impl-trait/unsize_tuple.rs
@@ -1,4 +1,6 @@
-//! Test that we do not allow unsizing `([Opaque; N],)` to `([Concrete],)`.
+//! Test that we allow unsizing `([Opaque; N],)` to `([Concrete],)`.
+
+//@check-pass
 
 #![feature(unsized_tuple_coercion)]
 
@@ -6,7 +8,6 @@ fn hello() -> ([impl Sized; 2],) {
     if false {
         let x = hello();
         let _: &([i32],) = &x;
-        //~^ ERROR: mismatched types
     }
     todo!()
 }
diff --git a/tests/ui/impl-trait/unsize_tuple.stderr b/tests/ui/impl-trait/unsize_tuple.stderr
deleted file mode 100644
index 8d3cf15887c..00000000000
--- a/tests/ui/impl-trait/unsize_tuple.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/unsize_tuple.rs:8:28
-   |
-LL | fn hello() -> ([impl Sized; 2],) {
-   |                 ---------- the found opaque type
-...
-LL |         let _: &([i32],) = &x;
-   |                ---------   ^^ expected `&([i32],)`, found `&([impl Sized; 2],)`
-   |                |
-   |                expected due to this
-   |
-   = note: expected reference `&([i32],)`
-              found reference `&([impl Sized; 2],)`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/unsized_coercion.next.stderr b/tests/ui/impl-trait/unsized_coercion.next.stderr
new file mode 100644
index 00000000000..49ac3f1845f
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion.next.stderr
@@ -0,0 +1,26 @@
+error[E0271]: type mismatch resolving `impl Trait <: dyn Trait`
+  --> $DIR/unsized_coercion.rs:14:17
+   |
+LL |         let x = hello();
+   |                 ^^^^^^^ types differ
+
+error[E0308]: mismatched types
+  --> $DIR/unsized_coercion.rs:18:14
+   |
+LL | fn hello() -> Box<impl Trait> {
+   |                   ---------- the expected opaque type
+...
+LL |     Box::new(1u32)
+   |     -------- ^^^^ types differ
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected opaque type `impl Trait`
+                     found type `u32`
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0271, E0308.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/unsized_coercion.rs b/tests/ui/impl-trait/unsized_coercion.rs
new file mode 100644
index 00000000000..46e040c1428
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion.rs
@@ -0,0 +1,21 @@
+//! This test checks that opaque types get unsized instead of
+//! constraining their hidden type to a trait object.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+//@[old] check-pass
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+fn hello() -> Box<impl Trait> {
+    if true {
+        let x = hello();
+        //[next]~^ ERROR: type mismatch resolving `impl Trait <: dyn Trait`
+        let y: Box<dyn Trait> = x;
+    }
+    Box::new(1u32) //[next]~ ERROR: mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsized_coercion2.old.stderr b/tests/ui/impl-trait/unsized_coercion2.old.stderr
new file mode 100644
index 00000000000..a89d40f1130
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion2.old.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
+  --> $DIR/unsized_coercion2.rs:15:33
+   |
+LL |         let y: Box<dyn Trait> = x;
+   |                                 ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
+   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion2.rs b/tests/ui/impl-trait/unsized_coercion2.rs
new file mode 100644
index 00000000000..7368d47dbe2
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion2.rs
@@ -0,0 +1,21 @@
+//! This test checks that opaque types get unsized instead of
+//! constraining their hidden type to a trait object.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+fn hello() -> Box<impl Trait + ?Sized> {
+    if true {
+        let x = hello();
+        let y: Box<dyn Trait> = x;
+        //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
+    }
+    Box::new(1u32)
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr
new file mode 100644
index 00000000000..bab8d1cd83b
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr
@@ -0,0 +1,38 @@
+error[E0271]: type mismatch resolving `impl Trait + ?Sized <: dyn Send`
+  --> $DIR/unsized_coercion3.rs:13:17
+   |
+LL |         let x = hello();
+   |                 ^^^^^^^ types differ
+
+error[E0308]: mismatched types
+  --> $DIR/unsized_coercion3.rs:19:14
+   |
+LL | fn hello() -> Box<impl Trait + ?Sized> {
+   |                   ------------------- the expected opaque type
+...
+LL |     Box::new(1u32)
+   |     -------- ^^^^ types differ
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected opaque type `impl Trait + ?Sized`
+                     found type `u32`
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
+  --> $DIR/unsized_coercion3.rs:19:14
+   |
+LL |     Box::new(1u32)
+   |     -------- ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
+note: required by a bound in `Box::<T>::new`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0271, E0277, E0308.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/unsized_coercion3.old.stderr b/tests/ui/impl-trait/unsized_coercion3.old.stderr
new file mode 100644
index 00000000000..24a302d7007
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion3.old.stderr
@@ -0,0 +1,26 @@
+error: cannot check whether the hidden type of opaque type satisfies auto traits
+  --> $DIR/unsized_coercion3.rs:15:32
+   |
+LL |         let y: Box<dyn Send> = x;
+   |                                ^
+   |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
+note: opaque type is declared here
+  --> $DIR/unsized_coercion3.rs:11:19
+   |
+LL | fn hello() -> Box<impl Trait + ?Sized> {
+   |                   ^^^^^^^^^^^^^^^^^^^
+   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`
+
+error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
+  --> $DIR/unsized_coercion3.rs:15:32
+   |
+LL |         let y: Box<dyn Send> = x;
+   |                                ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
+   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion3.rs b/tests/ui/impl-trait/unsized_coercion3.rs
new file mode 100644
index 00000000000..85950ac583e
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion3.rs
@@ -0,0 +1,24 @@
+//! This test checks that opaque types get unsized instead of
+//! constraining their hidden type to a trait object.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+fn hello() -> Box<impl Trait + ?Sized> {
+    if true {
+        let x = hello();
+        //[next]~^ ERROR: type mismatch resolving `impl Trait + ?Sized <: dyn Send`
+        let y: Box<dyn Send> = x;
+        //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
+        //[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
+    }
+    Box::new(1u32)
+    //[next]~^ ERROR: mismatched types
+    //[next]~| ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsized_coercion4.rs b/tests/ui/impl-trait/unsized_coercion4.rs
new file mode 100644
index 00000000000..1c4d5462cee
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion4.rs
@@ -0,0 +1,20 @@
+//! This test checks that opaque types get unsized instead of
+//! constraining their hidden type to a trait object.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+//@check-pass
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+fn hello() -> Box<impl Trait + ?Sized> {
+    if true {
+        let x = hello() as Box<u32>;
+        let y: Box<dyn Send> = x;
+    }
+    Box::new(1u32)
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsized_coercion5.next.stderr b/tests/ui/impl-trait/unsized_coercion5.next.stderr
new file mode 100644
index 00000000000..5644ac7ab04
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion5.next.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/unsized_coercion5.rs:16:32
+   |
+LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
+   |                -------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
+   |                |
+   |                expected due to this
+   |
+   = note: expected struct `Box<dyn Send>`
+              found struct `Box<dyn Trait + Send>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/unsized_coercion5.old.stderr b/tests/ui/impl-trait/unsized_coercion5.old.stderr
new file mode 100644
index 00000000000..b6437266f27
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion5.old.stderr
@@ -0,0 +1,38 @@
+error[E0308]: mismatched types
+  --> $DIR/unsized_coercion5.rs:16:32
+   |
+LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
+   |                -------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
+   |                |
+   |                expected due to this
+   |
+   = note: expected struct `Box<dyn Send>`
+              found struct `Box<dyn Trait + Send>`
+
+error: cannot check whether the hidden type of opaque type satisfies auto traits
+  --> $DIR/unsized_coercion5.rs:16:32
+   |
+LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
+   |                                ^
+   |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
+note: opaque type is declared here
+  --> $DIR/unsized_coercion5.rs:13:19
+   |
+LL | fn hello() -> Box<impl Trait + ?Sized> {
+   |                   ^^^^^^^^^^^^^^^^^^^
+   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
+
+error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
+  --> $DIR/unsized_coercion5.rs:16:32
+   |
+LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
+   |                                ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
+   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion5.rs b/tests/ui/impl-trait/unsized_coercion5.rs
new file mode 100644
index 00000000000..b007267a006
--- /dev/null
+++ b/tests/ui/impl-trait/unsized_coercion5.rs
@@ -0,0 +1,24 @@
+//! This test checks that opaque types get unsized instead of
+//! constraining their hidden type to a trait object.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+
+#![feature(trait_upcasting)]
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+fn hello() -> Box<impl Trait + ?Sized> {
+    if true {
+        let x = hello();
+        let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
+        //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
+        //[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
+        //~^^^ ERROR: mismatched types
+    }
+    Box::new(1u32)
+}
+
+fn main() {}