From e7b7d5b16148a645bce8f0c5d2f5ffacf68398bc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Aug 2026 09:33:14 +0200 Subject: [PATCH] peel_transparent_wrappers only works on non-1ZST --- compiler/rustc_abi/src/layout/ty.rs | 19 +++++++++++++++---- compiler/rustc_codegen_ssa/src/mir/place.rs | 6 ++++-- .../rustc_codegen_ssa/src/traits/builder.rs | 13 +++++++------ .../src/hir_ty_lowering/cmse.rs | 2 +- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 7c878cc619472..efa61348920d1 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -259,15 +259,25 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { where Ty: TyAbiInterface<'a, C> + Copy, { - let base = self.peel_transparent_wrappers(cx); + // FIXME: Peeling the wrappers above would not work correctly if we are a 1-ZST. So we make + // `#[rustc_pass_indirectly_in_non_rustic_abis]` a NOP on 1-ZST. In the future, + // `non_1zst_field` should become `non_trivial_abi_field` and + // `#[rustc_pass_indirectly_in_non_rustic_abis]` should make a type have non-trivial ABI. + if self.is_1zst() { + return false; + } + + let base = self.peel_transparent_wrappers_from_non_1zst(cx); Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base) } /// Recursively peel away transparent wrappers, returning the inner value. + /// Will not peel anything if `self` is a 1-ZST! Callers need to either check + /// that the result is not a 1-ZST, or have separate logic for that. /// /// The return value is not `repr(transparent)` and/or does /// not have a non-1zst field. - pub fn peel_transparent_wrappers(mut self, cx: &C) -> Self + pub fn peel_transparent_wrappers_from_non_1zst(mut self, cx: &C) -> Self where Ty: TyAbiInterface<'a, C> + Copy, { @@ -308,12 +318,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { where Ty: TyAbiInterface<'a, C> + Copy, { - let complex = self.peel_transparent_wrappers(cx); + // We're checking for scalar repr below which excludes 1-ZST. + let complex = self.peel_transparent_wrappers_from_non_1zst(cx); if !Ty::is_complex_number_lang_item(complex, cx) { return None; } - let part = complex.field(cx, 0).peel_transparent_wrappers(cx); + let part = complex.field(cx, 0).peel_transparent_wrappers_from_non_1zst(cx); if let BackendRepr::Scalar(scalar) = part.backend_repr { // Only Complex<{ float }> and Complex<{ integer }> have special layout. diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index dff1b18ee95b2..1613634d5a293 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -112,7 +112,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, layout: TyAndLayout<'tcx>, ) -> Self { - if layout.peel_transparent_wrappers(bx).deref().is_scalable_vector() { + // Scalable vector are never 1-ZST. FIXME: is that correct? + if layout.peel_transparent_wrappers_from_non_1zst(bx).deref().is_scalable_vector() { Self::alloca_scalable(bx, layout) } else { Self::alloca_size(bx, layout.size, layout) @@ -159,7 +160,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { layout: TyAndLayout<'tcx>, ) -> Self { PlaceValue::new_sized( - bx.alloca_with_ty(layout.peel_transparent_wrappers(bx)), + // FIXME why is this peeling at all? And why is it redoing the work the caller just did? + bx.alloca_with_ty(layout.peel_transparent_wrappers_from_non_1zst(bx)), layout.align.abi, ) .with_type(layout) diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 56dc13b832032..6113eccfe1565 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -528,12 +528,13 @@ pub trait BuilderMethods<'a, 'tcx>: let tt = tt.add_indirection(); let fnc_tree = FncTree { args: vec![tt.clone(), tt], ret: TypeTree::new() }; let bytes = self.const_usize(layout.size.bytes()); - let bytes = if layout.peel_transparent_wrappers(self).ty.is_scalable_vector() { - let vscale = self.vscale(self.type_i64()); - self.mul(vscale, bytes) - } else { - bytes - }; + let bytes = + if layout.peel_transparent_wrappers_from_non_1zst(self).ty.is_scalable_vector() { + let vscale = self.vscale(self.type_i64()); + self.mul(vscale, bytes) + } else { + bytes + }; self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags, Some(fnc_tree)); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index e4874c41d5cdd..d5dd338dff940 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -171,7 +171,7 @@ fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tc // Accept (transparently wrapped) scalar 64-bit primitives. matches!( - layout.peel_transparent_wrappers(&cx).ty.kind(), + layout.peel_transparent_wrappers_from_non_1zst(&cx).ty.kind(), ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64) ) }