Skip to content
/ rust Public
forked from rust-lang/rust

Commit aab8619

Browse files
authored
Rollup merge of rust-lang#157905 - zachs18:randomize-layout-zst-note, r=davidtwco
Update comments and add tests for `-Zrandomize-layout` for some guaranteed ZSTs See rust-lang/reference#2262 . T-lang wants to make some additional guarantees about zero-sized `repr(Rust)` structs and enums, that changes to `-Zrandomize-layout` could theoretically break in the future. This PR adds comments to `-Zrandomize-layout`'s implementation and tests to `tests/ui/layout/randomize.rs` to prevent breaking those guarantees. First commit is the guarantees that T-lang already FCP'd in rust-lang/reference#2262 . Second commit is an additional guarantee (that zero-variant repr(Rust) enums are ZSTs) that's at rust-lang/reference#2293 (FCP now completed)
2 parents 095cfe1 + bec5d88 commit aab8619

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

compiler/rustc_abi/src/layout.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,11 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
11321132
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
11331133
// the field ordering to try and catch some code making assumptions about layouts
11341134
// we don't guarantee.
1135+
// In the future, we might do more than shuffle field order (e.g. introduce extra padding),
1136+
// but never for `repr(Rust)` structs with only zero-sized fields, single-variant
1137+
// `repr(Rust)` enums with only zero-sized fields, or zero-variant `repr(Rust)` enums,
1138+
// which must remain zero-sized as per T-lang decisions in
1139+
// https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293
11351140
if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
11361141
#[cfg(feature = "randomize")]
11371142
{

compiler/rustc_abi/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ bitflags! {
9090
/// If true, the type's crate has opted into layout randomization.
9191
/// Other flags can still inhibit reordering and thus randomization.
9292
/// The seed stored in `ReprOptions.field_shuffle_seed`.
93+
///
94+
/// `repr(Rust)` structs with only zero-sized fields, single-variant `repr(Rust)` enums with only
95+
/// zero-sized fields, and zero-variant `repr(Rust)` enums must remain zero-sized as per
96+
/// T-lang decisions in https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293
9397
const RANDOMIZE_LAYOUT = 1 << 4;
9498
/// If true, the type is always passed indirectly by non-Rustic ABIs.
9599
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.

tests/ui/layout/randomize.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,52 @@ const _: () = {
4949
assert!(std::mem::offset_of!(Result::<&usize, ()>, Ok.0) == 0);
5050
};
5151

52+
// these types only have their size checked, they're never constructed.
53+
// these repr(Rust) types must remain zero-sized.
54+
#[allow(dead_code)]
55+
pub struct UnitStruct;
56+
#[allow(dead_code)]
57+
pub struct EmptyTupleStruct();
58+
#[allow(dead_code)]
59+
pub struct EmptyStruct {}
60+
#[allow(dead_code)]
61+
pub struct ZstFieldsTupleStruct((), [u64; 0], [u8; 0], [(); 42]);
62+
#[allow(dead_code)]
63+
pub struct ZstFieldsStruct {
64+
a: (),
65+
b: [u64; 0],
66+
c: [u8; 0],
67+
d: [(); 42],
68+
}
69+
#[allow(dead_code)]
70+
pub enum EmptyEnum {}
71+
#[allow(dead_code)]
72+
pub enum SingleUnitVariantEnum { A }
73+
#[allow(dead_code)]
74+
pub enum SingleZstFieldTupleVariantEnum { A((), [u64; 0], [u8; 0], [(); 42]) }
75+
#[allow(dead_code)]
76+
pub enum SingleZstFieldVariantEnum {
77+
A {
78+
a: (),
79+
b: [u64; 0],
80+
c: [u8; 0],
81+
d: [(); 42],
82+
}
83+
}
84+
85+
// all these types must remain zero-sized.
86+
const _: () = {
87+
assert!(size_of::<UnitStruct>() == 0);
88+
assert!(size_of::<EmptyTupleStruct>() == 0);
89+
assert!(size_of::<EmptyStruct>() == 0);
90+
assert!(size_of::<ZstFieldsTupleStruct>() == 0);
91+
assert!(size_of::<ZstFieldsStruct>() == 0);
92+
assert!(size_of::<EmptyEnum>() == 0);
93+
assert!(size_of::<SingleUnitVariantEnum>() == 0);
94+
assert!(size_of::<SingleZstFieldTupleVariantEnum>() == 0);
95+
assert!(size_of::<SingleZstFieldVariantEnum>() == 0);
96+
};
97+
5298
#[allow(dead_code)]
5399
struct Unsizable<T: ?Sized>(usize, T);
54100

0 commit comments

Comments
 (0)