From 68cfe93c112699e0651eb54e4a4de4b3a14cb5cc 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 003e811dc7855..a433761e73797 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1124,6 +1124,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 c2069432e6f8e..97bef297b6ef5 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -90,6 +90,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 bec5d880be77a942f3fc88eb20732e67e029dd93 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 a433761e73797..7f1a7021f5bcc 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1125,9 +1125,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 97bef297b6ef5..2a7dde3b8840e 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -91,9 +91,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);