From dface0a9cfd90aa6a1f8d72229bca8803dd0fd82 Mon Sep 17 00:00:00 2001 From: cijiugechu Date: Tue, 21 Apr 2026 21:29:56 +0800 Subject: [PATCH] Fix ICE: Scalar layout for non-primitive non-enum type unsafe binder --- .../rustc_ty_utils/src/layout/invariant.rs | 10 +++++++++- tests/ui/unsafe-binders/layout-invariant.rs | 17 +++++++++++++++++ .../ui/unsafe-binders/layout-invariant.stderr | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/ui/unsafe-binders/layout-invariant.rs create mode 100644 tests/ui/unsafe-binders/layout-invariant.stderr diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 03ac1674dbd50..a9edaa7371a88 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -1,8 +1,8 @@ use std::assert_matches; use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, TagEncoding, Variants}; -use rustc_middle::bug; use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; +use rustc_middle::{bug, ty}; /// Enforce some basic invariants on layouts. pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { @@ -52,6 +52,14 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou } fn skip_newtypes<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) -> TyAndLayout<'tcx> { + match *layout.ty.kind() { + ty::UnsafeBinder(bound_ty) => { + let ty = cx.tcx().instantiate_bound_regions_with_erased(bound_ty.into()); + return skip_newtypes(cx, &TyAndLayout { ty, ..*layout }); + } + _ => {} + } + if matches!(layout.layout.variants(), Variants::Multiple { .. }) { // Definitely not a newtype of anything. return *layout; diff --git a/tests/ui/unsafe-binders/layout-invariant.rs b/tests/ui/unsafe-binders/layout-invariant.rs new file mode 100644 index 0000000000000..46fb2e2839eae --- /dev/null +++ b/tests/ui/unsafe-binders/layout-invariant.rs @@ -0,0 +1,17 @@ +// Regression test for https://github.com/rust-lang/rust/issues/154426 +#![feature(unsafe_binders)] + +#[derive(Copy, Clone)] +struct Adt<'a> { + a: &'a String, +} + +const None: Option Option Adt<'a>>> = None; +//~^ ERROR the trait bound `unsafe<'a> Adt<'a>: Copy` is not satisfied +//~| ERROR the trait bound `unsafe<'a> Adt<'a>: Copy` is not satisfied + +fn main() { + match None { + _ => {} + }; +} diff --git a/tests/ui/unsafe-binders/layout-invariant.stderr b/tests/ui/unsafe-binders/layout-invariant.stderr new file mode 100644 index 0000000000000..8eb00897c8520 --- /dev/null +++ b/tests/ui/unsafe-binders/layout-invariant.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `unsafe<'a> Adt<'a>: Copy` is not satisfied + --> $DIR/layout-invariant.rs:9:13 + | +LL | const None: Option Option Adt<'a>>> = None; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `unsafe<'a> Adt<'a>` + | + = note: required for `Option Adt<'a>>` to implement `Copy` + +error[E0277]: the trait bound `unsafe<'a> Adt<'a>: Copy` is not satisfied + --> $DIR/layout-invariant.rs:9:59 + | +LL | const None: Option Option Adt<'a>>> = None; + | ^^^^ the trait `Copy` is not implemented for `unsafe<'a> Adt<'a>` + | + = note: required for `Option Adt<'a>>` to implement `Copy` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.