From 32f69490862fae404ea0f4917ac50ceab27f4a41 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 15 Jun 2026 00:47:48 -0500 Subject: [PATCH 1/2] Add comments to randomize-layout implementation documenting guaranteed ZST struct/enums. Also add tests for the guaranteed types. --- compiler/rustc_abi/src/layout.rs | 4 +++ compiler/rustc_abi/src/lib.rs | 4 +++ tests/ui/layout/randomize.rs | 43 ++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 7b68fbc9e77b0..49176250a14c2 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1121,6 +1121,10 @@ impl LayoutCalculator { // If `-Z randomize-layout` was enabled for the type definition we can shuffle // the field ordering to try and catch some code making assumptions about layouts // we don't guarantee. + // In the future, we might do more than shuffle field order (e.g. introduce extra padding), + // but never for `repr(Rust)` structs with only zero-sized fields or single-variant + // `repr(Rust)` enums with only zero-sized fields, which must remain zero-sized as per + // T-lang decision https://github.com/rust-lang/reference/pull/2262 if repr.can_randomize_type_layout() && cfg!(feature = "randomize") { #[cfg(feature = "randomize")] { diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 166c8bea6f354..82bbf640ac646 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -89,6 +89,10 @@ bitflags! { /// If true, the type's crate has opted into layout randomization. /// Other flags can still inhibit reordering and thus randomization. /// The seed stored in `ReprOptions.field_shuffle_seed`. + /// + /// `repr(Rust)` structs with only zero-sized fields and single-variant `repr(Rust)` enums with only + /// zero-sized fields must remain zero-sized as per T-lang decision + /// https://github.com/rust-lang/reference/pull/2262 const RANDOMIZE_LAYOUT = 1 << 4; /// If true, the type is always passed indirectly by non-Rustic ABIs. /// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details. diff --git a/tests/ui/layout/randomize.rs b/tests/ui/layout/randomize.rs index 27e99327a3196..f25ee23009049 100644 --- a/tests/ui/layout/randomize.rs +++ b/tests/ui/layout/randomize.rs @@ -49,6 +49,49 @@ const _: () = { assert!(std::mem::offset_of!(Result::<&usize, ()>, Ok.0) == 0); }; +// these types only have their size checked, they're never constructed. +// these repr(Rust) types must remain zero-sized. +#[allow(dead_code)] +pub struct UnitStruct; +#[allow(dead_code)] +pub struct EmptyTupleStruct(); +#[allow(dead_code)] +pub struct EmptyStruct {} +#[allow(dead_code)] +pub struct ZstFieldsTupleStruct((), [u64; 0], [u8; 0], [(); 42]); +#[allow(dead_code)] +pub struct ZstFieldsStruct { + a: (), + b: [u64; 0], + c: [u8; 0], + d: [(); 42], +} +#[allow(dead_code)] +pub enum SingleUnitVariantEnum { A } +#[allow(dead_code)] +pub enum SingleZstFieldTupleVariantEnum { A((), [u64; 0], [u8; 0], [(); 42]) } +#[allow(dead_code)] +pub enum SingleZstFieldVariantEnum { + A { + a: (), + b: [u64; 0], + c: [u8; 0], + d: [(); 42], + } +} + +// all these types must remain zero-sized. +const _: () = { + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); +}; + #[allow(dead_code)] struct Unsizable(usize, T); From 78ea28ba67e80b012e89df41243fc28d1dbafb42 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 15 Jun 2026 00:49:32 -0500 Subject: [PATCH 2/2] Add zero-variant enums to randomize-layout comments and tests. --- compiler/rustc_abi/src/layout.rs | 7 ++++--- compiler/rustc_abi/src/lib.rs | 6 +++--- tests/ui/layout/randomize.rs | 3 +++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 49176250a14c2..c6c6e53d83eac 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1122,9 +1122,10 @@ impl LayoutCalculator { // the field ordering to try and catch some code making assumptions about layouts // we don't guarantee. // In the future, we might do more than shuffle field order (e.g. introduce extra padding), - // but never for `repr(Rust)` structs with only zero-sized fields or single-variant - // `repr(Rust)` enums with only zero-sized fields, which must remain zero-sized as per - // T-lang decision https://github.com/rust-lang/reference/pull/2262 + // but never for `repr(Rust)` structs with only zero-sized fields, single-variant + // `repr(Rust)` enums with only zero-sized fields, or zero-variant `repr(Rust)` enums, + // which must remain zero-sized as per T-lang decisions in + // https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293 if repr.can_randomize_type_layout() && cfg!(feature = "randomize") { #[cfg(feature = "randomize")] { diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 82bbf640ac646..d246255f10355 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -90,9 +90,9 @@ bitflags! { /// Other flags can still inhibit reordering and thus randomization. /// The seed stored in `ReprOptions.field_shuffle_seed`. /// - /// `repr(Rust)` structs with only zero-sized fields and single-variant `repr(Rust)` enums with only - /// zero-sized fields must remain zero-sized as per T-lang decision - /// https://github.com/rust-lang/reference/pull/2262 + /// `repr(Rust)` structs with only zero-sized fields, single-variant `repr(Rust)` enums with only + /// zero-sized fields, and zero-variant `repr(Rust)` enums must remain zero-sized as per + /// T-lang decisions in https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293 const RANDOMIZE_LAYOUT = 1 << 4; /// If true, the type is always passed indirectly by non-Rustic ABIs. /// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details. diff --git a/tests/ui/layout/randomize.rs b/tests/ui/layout/randomize.rs index f25ee23009049..eaeb527f191cb 100644 --- a/tests/ui/layout/randomize.rs +++ b/tests/ui/layout/randomize.rs @@ -67,6 +67,8 @@ pub struct ZstFieldsStruct { d: [(); 42], } #[allow(dead_code)] +pub enum EmptyEnum {} +#[allow(dead_code)] pub enum SingleUnitVariantEnum { A } #[allow(dead_code)] pub enum SingleZstFieldTupleVariantEnum { A((), [u64; 0], [u8; 0], [(); 42]) } @@ -87,6 +89,7 @@ const _: () = { assert!(size_of::() == 0); assert!(size_of::() == 0); assert!(size_of::() == 0); + assert!(size_of::() == 0); assert!(size_of::() == 0); assert!(size_of::() == 0); assert!(size_of::() == 0);