Repository: rust-lang/rust
Pull request: Fix ICE in unsafe binder discriminant helpers

Forward discriminant-related helpers through `ty::UnsafeBinder` to the erased inner type, matching the existing layout behavior.

Tracking issue: rust-lang/rust#130516 
Closes rust-lang/rust#154424

<!-- homu-ignore:start -->
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r? <reviewer name>
-->
<!-- homu-ignore:end -->


Changed files:
filename: compiler/rustc_middle/src/ty/sty.rs
patch: @@ -1640,6 +1640,9 @@ impl<'tcx> Ty<'tcx> {
             TyKind::Coroutine(def_id, args) => {
                 Some(args.as_coroutine().variant_range(*def_id, tcx))
             }
+            TyKind::UnsafeBinder(bound_ty) => {
+                tcx.instantiate_bound_regions_with_erased((*bound_ty).into()).variant_range(tcx)
+            }
             _ => None,
         }
     }
@@ -1661,6 +1664,9 @@ impl<'tcx> Ty<'tcx> {
             TyKind::Coroutine(def_id, args) => {
                 Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index))
             }
+            TyKind::UnsafeBinder(bound_ty) => tcx
+                .instantiate_bound_regions_with_erased((*bound_ty).into())
+                .discriminant_for_variant(tcx, variant_index),
             _ => None,
         }
     }
@@ -1679,6 +1685,9 @@ impl<'tcx> Ty<'tcx> {
             }
 
             ty::Pat(ty, _) => ty.discriminant_ty(tcx),
+            ty::UnsafeBinder(bound_ty) => {
+                tcx.instantiate_bound_regions_with_erased((*bound_ty).into()).discriminant_ty(tcx)
+            }
 
             ty::Bool
             | ty::Char
@@ -1700,7 +1709,6 @@ impl<'tcx> Ty<'tcx> {
             | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
-            | ty::UnsafeBinder(_)
             | ty::Error(_)
             | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8,
 

filename: tests/ui/unsafe-binders/discriminant-for-variant.rs
patch: @@ -0,0 +1,11 @@
+#![feature(unsafe_binders)]
+
+const None: Option<unsafe<> Option<Box<dyn Send>>> = None;
+//~^ ERROR the trait bound `Box<(dyn Send + 'static)>: Copy` is not satisfied
+//~| ERROR the trait bound `Box<(dyn Send + 'static)>: Copy` is not satisfied
+
+fn main() {
+    match None {
+        _ => {}
+    }
+}

filename: tests/ui/unsafe-binders/discriminant-for-variant.stderr
patch: @@ -0,0 +1,19 @@
+error[E0277]: the trait bound `Box<(dyn Send + 'static)>: Copy` is not satisfied
+  --> $DIR/discriminant-for-variant.rs:3:13
+   |
+LL | const None: Option<unsafe<> Option<Box<dyn Send>>> = None;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<(dyn Send + 'static)>`
+   |
+   = note: required for `Option<Box<(dyn Send + 'static)>>` to implement `Copy`
+
+error[E0277]: the trait bound `Box<(dyn Send + 'static)>: Copy` is not satisfied
+  --> $DIR/discriminant-for-variant.rs:3:54
+   |
+LL | const None: Option<unsafe<> Option<Box<dyn Send>>> = None;
+   |                                                      ^^^^ the trait `Copy` is not implemented for `Box<(dyn Send + 'static)>`
+   |
+   = note: required for `Option<Box<(dyn Send + 'static)>>` to implement `Copy`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.