Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,11 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
// 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, 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")]
{
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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.
Expand Down
46 changes: 46 additions & 0 deletions tests/ui/layout/randomize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,52 @@ 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 EmptyEnum {}
#[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::<UnitStruct>() == 0);
assert!(size_of::<EmptyTupleStruct>() == 0);
assert!(size_of::<EmptyStruct>() == 0);
assert!(size_of::<ZstFieldsTupleStruct>() == 0);
assert!(size_of::<ZstFieldsStruct>() == 0);
assert!(size_of::<EmptyEnum>() == 0);
assert!(size_of::<SingleUnitVariantEnum>() == 0);
assert!(size_of::<SingleZstFieldTupleVariantEnum>() == 0);
assert!(size_of::<SingleZstFieldVariantEnum>() == 0);
};

#[allow(dead_code)]
struct Unsizable<T: ?Sized>(usize, T);

Expand Down
Loading