diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index af599108c49dc..f883cd7189387 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1161,7 +1161,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.
@@ -1228,7 +1228,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)
@@ -1276,7 +1276,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);
 
@@ -1309,7 +1309,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 0000000000000..ce811004fae19
--- /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 0000000000000..bed88db1accee
--- /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 0000000000000..92da47b08e9f1
--- /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 fce5094bd404c..825384b61e87a 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 2b93b4a571b1b..0000000000000
--- 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 ec0f162656400..b0cf1c7ca6d26 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 6a7fdb46163b9..0000000000000
--- 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 630b8fd430f1a..2678564f0e869 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 8d3cf15887c08..0000000000000
--- 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 0000000000000..49ac3f1845fb3
--- /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 0000000000000..46e040c1428a4
--- /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 0000000000000..a89d40f1130c1
--- /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 0000000000000..7368d47dbe2c0
--- /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 0000000000000..bab8d1cd83b30
--- /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 0000000000000..24a302d7007ab
--- /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 0000000000000..85950ac583ebc
--- /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 0000000000000..1c4d5462ceeb2
--- /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 0000000000000..5644ac7ab04bc
--- /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 0000000000000..b6437266f27dd
--- /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 0000000000000..b007267a0066f
--- /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() {}