From 07c2864d4495c177acba692fbe3dc13e77b52a67 Mon Sep 17 00:00:00 2001 From: GokhanKabar Date: Mon, 13 Apr 2026 23:13:48 +0200 Subject: [PATCH] Fix ICE in pointer layout for DSTs with bogus Sized impls A bogus `impl Sized for T {}` (rejected as E0322) was processed by the new trait solver (`-Znext-solver=globally`), making DSTs like `[T]` appear sized. This caused `*const [T]` to receive a thin-pointer (Scalar) layout instead of a fat-pointer (ScalarPair) layout. When const evaluation then performed an array-to-slice unsizing coercion and tried to write a ScalarPair value to a Scalar-layout place, it triggered an ICE: "invalid immediate for given destination place: value ScalarPair(...) does not match ABI Scalar(...)" The fix adds a structural cross-check in the pointer layout computation: after `is_sized` returns true, we verify via `struct_tail_for_codegen` (which is purely structural and unaffected by bogus trait impls) that the pointee tail is not a known DST kind (Slice/Str/Dynamic). If it is, we skip the thin-pointer early return and fall through to compute the correct fat-pointer layout. --- compiler/rustc_ty_utils/src/layout.rs | 13 ++++++++++- ...-ice-on-bogus-sized-impl-in-const-block.rs | 22 +++++++++++++++++++ ...-on-bogus-sized-impl-in-const-block.stderr | 19 ++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.rs create mode 100644 tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.stderr diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 136df923ee47a..f407188ab73e9 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -414,7 +414,18 @@ fn layout_of_uncached<'tcx>( } if pointee.is_sized(tcx, cx.typing_env) { - return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); + // Guard against bogus `impl Sized` declarations (e.g., + // `impl Sized for T {}`), which are rejected with E0322 + // but can still be processed by the trait solver in erroneous code. + // Such impls can make DSTs like `[T]`, `str`, and `dyn Trait` appear + // sized, causing pointer layout to be incorrectly computed as a thin + // pointer (Scalar) instead of a fat pointer (ScalarPair). We guard + // against this by checking the type kind directly (O(1), no recursion). + if !matches!(pointee.kind(), ty::Slice(_) | ty::Str | ty::Dynamic(..)) { + return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); + } + // The pointee is structurally a DST — `is_sized` is unreliable here. + // Fall through to compute the correct fat-pointer layout below. } let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { diff --git a/tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.rs b/tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.rs new file mode 100644 index 0000000000000..1c9a6cb57a275 --- /dev/null +++ b/tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver=globally + +// A bogus `impl Sized for T` (rejected with E0322) used to cause an ICE when +// the new trait solver processed it and made DSTs like `[T]` appear sized. This +// caused pointer layout to be computed as a thin-pointer (Scalar) instead of a +// fat-pointer (ScalarPair), and const evaluation of unsafe pointer arithmetic +// inside a `const {}` block would then ICE with: +// "invalid immediate for given destination place: value ScalarPair(...) does +// not match ABI Scalar(...)" + +impl<'a, T: ?Sized> Sized for T {} +//~^ ERROR explicit impls for the `Sized` trait are not permitted +//~| ERROR type parameter `T` must be used as the type parameter for some local type + +fn main() { + const { + unsafe { + let value = [1, 2]; + let _ptr = value.as_ptr().add(2); + } + } +} diff --git a/tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.stderr b/tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.stderr new file mode 100644 index 0000000000000..bcb0670abdd29 --- /dev/null +++ b/tests/ui/traits/next-solver/dont-ice-on-bogus-sized-impl-in-const-block.stderr @@ -0,0 +1,19 @@ +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/dont-ice-on-bogus-sized-impl-in-const-block.rs:11:1 + | +LL | impl<'a, T: ?Sized> Sized for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/dont-ice-on-bogus-sized-impl-in-const-block.rs:11:10 + | +LL | impl<'a, T: ?Sized> Sized for T {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0210, E0322. +For more information about an error, try `rustc --explain E0210`.