diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 7bffeaf4cc9e2..7bf0396ec9347 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1167,6 +1167,23 @@ impl LayoutCalculator { } // Otherwise we just leave things alone and actually optimize the type's fields } else { + // Equal to can_randomize_type_layout, only doesn't need the -Zrandomize-layout + // flag + if !repr.never_randomize_type_layout() && cfg!(feature = "randomize") { + #[cfg(feature = "randomize")] + { + use rand::SeedableRng; + use rand::seq::SliceRandom; + // `ReprOptions.field_shuffle_seed` is a deterministic seed we can use to randomize field + // ordering. + let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64( + field_seed.wrapping_add(repr.field_shuffle_seed).as_u64(), + ); + + // Shuffle the ordering of the fields. + optimizing.shuffle(&mut rng); + } + } // To allow unsizing `&Foo` -> `&Foo`, the layout of the struct must // not depend on the layout of the tail. let max_field_align = diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 59b74d2922145..ae9d106a12515 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -92,6 +92,10 @@ bitflags! { // Other flags can still inhibit reordering and thus randomization. // The seed stored in `ReprOptions.field_shuffle_seed`. const RANDOMIZE_LAYOUT = 1 << 4; + // If true, the type itself has opted out of layout randomization, even under the + // "default-enabled" mode. Internal only, just used for tests that assume the layout of + // types. Does *not* inhibit reordering, just randomization. + const NEVER_RANDOMIZE_LAYOUT = 1 << 5; // Any of these flags being set prevent field reordering optimisation. const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits() @@ -207,6 +211,12 @@ impl ReprOptions { !self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) } + pub fn never_randomize_type_layout(&self) -> bool { + self.inhibit_struct_field_reordering() + || self.flags.contains(ReprFlags::NEVER_RANDOMIZE_LAYOUT) + || self.packed() + } + /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. pub fn inhibits_union_abi_opt(&self) -> bool { self.c() diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 969bce7ae20a6..7a1521a7e1b73 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -192,6 +192,7 @@ pub enum AttributeKind { MacroTransparency(Transparency), Repr(ThinVec<(ReprAttr, Span)>), RustcMacroEdition2021, + RustcNeverRandomizeLayout, Stability { stability: Stability, /// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 1e33e2e9393f7..1b718b0f3a11c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -893,6 +893,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (note that the compiler does not even check whether the type indeed is being non-null-optimized; \ it is your responsibility to ensure that the attribute is only used on types that are optimized)", ), + rustc_attr!( + rustc_never_randomize_layout, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::Yes, + "the `#[rustc_never_randomize_layout]` attribute is just used to inhibit \ + field randomization in rustc tests", + ), // ========================================================================== // Internal attributes, Misc: diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 80f1bd7c6f464..83938235eb295 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1484,6 +1484,15 @@ impl<'tcx> TyCtxt<'tcx> { field_shuffle_seed ^= user_seed; } + if self.has_attr(did, sym::rustc_never_randomize_layout) { + flags.insert(ReprFlags::NEVER_RANDOMIZE_LAYOUT); + } + + // Never randomize layout if we're not running under debug assertions. + if !self.sess.opts.debug_assertions { + flags.insert(ReprFlags::NEVER_RANDOMIZE_LAYOUT); + } + if let Some(reprs) = attr::find_attr!(self.get_all_attrs(did), AttributeKind::Repr(r) => r) { for (r, _) in reprs { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 31847ae3b4658..2d96558488217 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1825,6 +1825,7 @@ symbols! { rustc_main, rustc_mir, rustc_must_implement_one_of, + rustc_never_randomize_layout, rustc_never_returns_null_ptr, rustc_never_type_options, rustc_no_mir_inline, diff --git a/tests/assembly/issue-83585-small-pod-struct-equality.rs b/tests/assembly/issue-83585-small-pod-struct-equality.rs index 14bec1337f0bf..f3f5195a1a646 100644 --- a/tests/assembly/issue-83585-small-pod-struct-equality.rs +++ b/tests/assembly/issue-83585-small-pod-struct-equality.rs @@ -1,6 +1,7 @@ //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 //@ only-x86_64 +//@ ignore-std-debug-assertions #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs index 7fb850ca2532a..508b3e46e900a 100644 --- a/tests/codegen/issues/issue-101082.rs +++ b/tests/codegen/issues/issue-101082.rs @@ -1,6 +1,7 @@ //@ compile-flags: -Copt-level=3 //@ revisions: host x86-64-v3 //@ min-llvm-version: 20 +//@ ignore-std-debug-assertions // This particular CPU regressed in #131563 //@[x86-64-v3] only-x86_64 diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index c2f5e83d6868f..2f1be79ae026c 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,19 +2,22 @@ //@ test-mir-pass: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of_enum)] +#![feature(offset_of_enum, rustc_attrs)] use std::marker::PhantomData; use std::mem::offset_of; +#[rustc_never_randomize_layout] struct Alpha { x: u8, y: u16, z: Beta, } +#[rustc_never_randomize_layout] struct Beta(u8, u8); +#[rustc_never_randomize_layout] struct Gamma { x: u8, y: u16, diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index bb4a74d3712a0..7837cc03bfd23 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -1,17 +1,21 @@ //@ test-mir-pass: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +#![feature(rustc_attrs)] use std::marker::PhantomData; use std::mem::offset_of; +#[rustc_never_randomize_layout] struct Alpha { x: u8, y: u16, z: Beta, } +#[rustc_never_randomize_layout] struct Beta(u8, u8); +#[rustc_never_randomize_layout] struct Gamma { x: u8, y: u16, diff --git a/tests/ui/abi/abi-sysv64-arg-passing.rs b/tests/ui/abi/abi-sysv64-arg-passing.rs index c18752418a1d6..f9fc24a3b936d 100644 --- a/tests/ui/abi/abi-sysv64-arg-passing.rs +++ b/tests/ui/abi/abi-sysv64-arg-passing.rs @@ -87,6 +87,7 @@ mod tests { pub struct Quad { a: u64, b: u64, c: u64, d: u64 } #[derive(Copy, Clone)] + #[repr(C)] pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 } #[repr(C)] diff --git a/tests/ui/abi/extern/extern-return-FiveU16s.rs b/tests/ui/abi/extern/extern-return-FiveU16s.rs index d8ae8b2661c5a..2ed05cf46f0a3 100644 --- a/tests/ui/abi/extern/extern-return-FiveU16s.rs +++ b/tests/ui/abi/extern/extern-return-FiveU16s.rs @@ -1,6 +1,7 @@ //@ run-pass #![allow(improper_ctypes)] +#[repr(C)] pub struct FiveU16s { one: u16, two: u16, diff --git a/tests/ui/abi/issue-28676.rs b/tests/ui/abi/issue-28676.rs index 8640f5aad21c9..dce2e5aaeffe7 100644 --- a/tests/ui/abi/issue-28676.rs +++ b/tests/ui/abi/issue-28676.rs @@ -3,6 +3,7 @@ #![allow(improper_ctypes)] #[derive(Copy, Clone)] +#[repr(C)] pub struct Quad { a: u64, b: u64, diff --git a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs index 314db42280d99..f063dbe0bcbbf 100644 --- a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs +++ b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs @@ -3,6 +3,7 @@ #![allow(improper_ctypes)] #[derive(Copy, Clone)] +#[repr(C)] pub struct QuadFloats { a: f32, b: f32, diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index f400073aca215..c552906eada2c 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -54,7 +54,7 @@ LL | const INVALID_VTABLE_UB: W<&dyn Trait> = } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-incorrect-vtable.rs:91:1 + --> $DIR/ub-incorrect-vtable.rs:94:1 | LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | ^^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation) diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs index 8058f7693a71c..1d419cefa3234 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -49,8 +49,10 @@ const INVALID_VTABLE_UB: W<&dyn Trait> = // Trying to access the data in a vtable does not work, either. #[derive(Copy, Clone)] +#[repr(C)] struct Wide<'a>(&'a Foo, &'static VTable); +#[repr(C)] struct VTable { drop: Option fn(&'a mut Foo)>, size: usize, @@ -62,6 +64,7 @@ trait Bar { fn bar(&self) -> u32; } +#[repr(C)] struct Foo { foo: u32, bar: bool, diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index 90e3c58dad719..81829b10e4b2d 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -4,10 +4,12 @@ #![crate_type = "lib"] #[rustc_layout(debug)] +#[rustc_never_randomize_layout] #[derive(Copy, Clone)] enum E { Foo, Bar(!, i32, i32) } //~ ERROR: layout_of #[rustc_layout(debug)] +#[rustc_never_randomize_layout] struct S { f1: i32, f2: (), f3: i32 } //~ ERROR: layout_of #[rustc_layout(debug)] diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index abaa16cdefacd..d77ad1a54a8b3 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -1,5 +1,5 @@ error: unions cannot have zero fields - --> $DIR/debug.rs:84:1 + --> $DIR/debug.rs:86:1 | LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^^^^ @@ -101,7 +101,7 @@ error: layout_of(E) = Layout { unadjusted_abi_align: Align(4 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:8:1 + --> $DIR/debug.rs:9:1 | LL | enum E { Foo, Bar(!, i32, i32) } | ^^^^^^ @@ -149,7 +149,7 @@ error: layout_of(S) = Layout { unadjusted_abi_align: Align(4 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:11:1 + --> $DIR/debug.rs:13:1 | LL | struct S { f1: i32, f2: (), f3: i32 } | ^^^^^^^^ @@ -175,7 +175,7 @@ error: layout_of(U) = Layout { unadjusted_abi_align: Align(4 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:14:1 + --> $DIR/debug.rs:16:1 | LL | union U { f1: (i32, i32), f3: i32 } | ^^^^^^^ @@ -316,7 +316,7 @@ error: layout_of(Result) = Layout { unadjusted_abi_align: Align(4 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:17:1 + --> $DIR/debug.rs:19:1 | LL | type Test = Result; | ^^^^^^^^^ @@ -346,7 +346,7 @@ error: layout_of(i32) = Layout { unadjusted_abi_align: Align(4 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:20:1 + --> $DIR/debug.rs:22:1 | LL | type T = impl std::fmt::Debug; | ^^^^^^ @@ -372,7 +372,7 @@ error: layout_of(V) = Layout { unadjusted_abi_align: Align(2 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:27:1 + --> $DIR/debug.rs:29:1 | LL | pub union V { | ^^^^^^^^^^^ @@ -398,7 +398,7 @@ error: layout_of(W) = Layout { unadjusted_abi_align: Align(2 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:33:1 + --> $DIR/debug.rs:35:1 | LL | pub union W { | ^^^^^^^^^^^ @@ -424,7 +424,7 @@ error: layout_of(Y) = Layout { unadjusted_abi_align: Align(2 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:39:1 + --> $DIR/debug.rs:41:1 | LL | pub union Y { | ^^^^^^^^^^^ @@ -450,7 +450,7 @@ error: layout_of(P1) = Layout { unadjusted_abi_align: Align(1 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:46:1 + --> $DIR/debug.rs:48:1 | LL | union P1 { x: u32 } | ^^^^^^^^ @@ -476,7 +476,7 @@ error: layout_of(P2) = Layout { unadjusted_abi_align: Align(1 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:50:1 + --> $DIR/debug.rs:52:1 | LL | union P2 { x: (u32, u32) } | ^^^^^^^^ @@ -502,7 +502,7 @@ error: layout_of(P3) = Layout { unadjusted_abi_align: Align(1 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:58:1 + --> $DIR/debug.rs:60:1 | LL | union P3 { x: F32x4 } | ^^^^^^^^ @@ -528,7 +528,7 @@ error: layout_of(P4) = Layout { unadjusted_abi_align: Align(1 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:62:1 + --> $DIR/debug.rs:64:1 | LL | union P4 { x: E } | ^^^^^^^^ @@ -559,7 +559,7 @@ error: layout_of(P5) = Layout { unadjusted_abi_align: Align(1 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:66:1 + --> $DIR/debug.rs:68:1 | LL | union P5 { zst: [u16; 0], byte: u8 } | ^^^^^^^^ @@ -590,19 +590,19 @@ error: layout_of(MaybeUninit) = Layout { unadjusted_abi_align: Align(1 bytes), randomization_seed: $SEED, } - --> $DIR/debug.rs:69:1 + --> $DIR/debug.rs:71:1 | LL | type X = std::mem::MaybeUninit; | ^^^^^^ error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases - --> $DIR/debug.rs:72:1 + --> $DIR/debug.rs:74:1 | LL | const C: () = (); | ^^^^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/debug.rs:80:19 + --> $DIR/debug.rs:82:19 | LL | type Impossible = (str, str); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -611,19 +611,19 @@ LL | type Impossible = (str, str); = note: only the last element of a tuple may have a dynamically sized type error: the type has an unknown layout - --> $DIR/debug.rs:84:1 + --> $DIR/debug.rs:86:1 | LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^ error: the type `T` does not have a fixed layout - --> $DIR/debug.rs:90:1 + --> $DIR/debug.rs:92:1 | LL | type TooGeneric = T; | ^^^^^^^^^^^^^^^^^^ error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases - --> $DIR/debug.rs:76:5 + --> $DIR/debug.rs:78:5 | LL | const C: () = (); | ^^^^^^^^^^^ diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs index 96c030b70e50f..2fa7bf010a1ef 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.rs +++ b/tests/ui/mir/mir_raw_fat_ptr.rs @@ -2,6 +2,7 @@ // check raw fat pointer ops in mir // FIXME: please improve this when we get monomorphization support +#![feature(rustc_attrs)] #![allow(ambiguous_wide_pointer_comparisons)] use std::mem; @@ -105,8 +106,12 @@ impl Foo for T { } #[allow(dead_code)] +#[rustc_never_randomize_layout] struct S(u32, T); +#[rustc_never_randomize_layout] +struct C(A, B, C); + fn main_ref() { let array = [0,1,2,3,4]; let array2 = [5,6,7,8,9]; @@ -143,9 +148,9 @@ fn main_ref() { assert_inorder(buf, compare_foo); // check ordering for structs containing arrays - let ss: (S<[u8; 2]>, + let ss: C, S<[u8; 3]>, - S<[u8; 2]>) = ( + S<[u8; 2]>> = C( S(7, [8, 9]), S(10, [11, 12, 13]), S(4, [5, 6]) @@ -197,9 +202,9 @@ fn main_raw() { assert_inorder(buf, compare_foo); // check ordering for structs containing arrays - let ss: (S<[u8; 2]>, + let ss: C, S<[u8; 3]>, - S<[u8; 2]>) = ( + S<[u8; 2]>> = C( S(7, [8, 9]), S(10, [11, 12, 13]), S(4, [5, 6]) diff --git a/tests/ui/mir/mir_raw_fat_ptr.stderr b/tests/ui/mir/mir_raw_fat_ptr.stderr index cd99d566654f9..a9e9dd66ebdfa 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.stderr +++ b/tests/ui/mir/mir_raw_fat_ptr.stderr @@ -1,5 +1,5 @@ warning: method `foo` is never used - --> $DIR/mir_raw_fat_ptr.rs:100:16 + --> $DIR/mir_raw_fat_ptr.rs:101:16 | LL | trait Foo { fn foo(&self) -> usize; } | --- ^^^ diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout index 83a6962e4cd13..b451680a34720 100644 --- a/tests/ui/print_type_sizes/async.stdout +++ b/tests/ui/print_type_sizes/async.stdout @@ -1,15 +1,18 @@ print-type-size type: `{async fn body of test()}`: 16386 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes -print-type-size variant `Unresumed`: 8192 bytes -print-type-size upvar `.arg`: 8192 bytes -print-type-size variant `Suspend0`: 16385 bytes -print-type-size upvar `.arg`: 8192 bytes -print-type-size local `.arg`: 8192 bytes +print-type-size variant `Unresumed`: 16385 bytes +print-type-size padding: 8193 bytes +print-type-size upvar `.arg`: 8192 bytes, alignment: 1 bytes +print-type-size variant `Suspend0`: 8193 bytes print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()} -print-type-size variant `Returned`: 8192 bytes -print-type-size upvar `.arg`: 8192 bytes -print-type-size variant `Panicked`: 8192 bytes +print-type-size local `.arg`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes +print-type-size variant `Returned`: 16385 bytes +print-type-size padding: 8193 bytes +print-type-size upvar `.arg`: 8192 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 16385 bytes +print-type-size padding: 8193 bytes +print-type-size upvar `.arg`: 8192 bytes, alignment: 1 bytes print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes print-type-size field `.value`: 8192 bytes print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes diff --git a/tests/ui/print_type_sizes/generics.rs b/tests/ui/print_type_sizes/generics.rs index af26dc690d27b..ee7341831b8b7 100644 --- a/tests/ui/print_type_sizes/generics.rs +++ b/tests/ui/print_type_sizes/generics.rs @@ -7,8 +7,10 @@ // This file illustrates how generics are handled: types have to be // monomorphized, in the MIR of the original function in which they // occur, to have their size reported. +#![feature(rustc_attrs)] #[derive(Copy, Clone)] +#[rustc_never_randomize_layout] pub struct Pair { _car: T, _cdr: T, diff --git a/tests/ui/print_type_sizes/packed.rs b/tests/ui/print_type_sizes/packed.rs index 888fa41a7597e..564476fe015e3 100644 --- a/tests/ui/print_type_sizes/packed.rs +++ b/tests/ui/print_type_sizes/packed.rs @@ -13,6 +13,7 @@ // padding and overall computed sizes can be quite different. #![allow(dead_code)] +#![feature(rustc_attrs)] #[derive(Default)] #[repr(packed)] @@ -49,6 +50,7 @@ pub struct Packed2C { } #[derive(Default)] +#[rustc_never_randomize_layout] pub struct Padded { a: u8, b: u8, diff --git a/tests/ui/print_type_sizes/zero-sized-fields.rs b/tests/ui/print_type_sizes/zero-sized-fields.rs index b3c4b684c6e80..c770f6c1abc46 100644 --- a/tests/ui/print_type_sizes/zero-sized-fields.rs +++ b/tests/ui/print_type_sizes/zero-sized-fields.rs @@ -4,7 +4,9 @@ // At one point, zero-sized fields such as those in this file were causing // incorrect output from `-Z print-type-sizes`. +#![feature(rustc_attrs)] +#[rustc_never_randomize_layout] struct S1 { x: u32, y: u32, @@ -14,6 +16,7 @@ struct S1 { struct Void(); struct Empty {} +#[rustc_never_randomize_layout] struct S5 { tagw: TagW, w: u32,