Skip to content

Commit 1098028

Browse files
fix: Adapts new enum layout to work in all editions.
The new implementation was only working for future edition, but since currently enum layout is not guaranteed, it adds the changes to all editions. Signed-off-by: Miguel Marques <miguel.m.marques@tecnico.ulisboa.pt> Co-authored-by: Vicente Gusmão <vicente.gusmao@tecnico.ulisboa.pt>
1 parent 5431efd commit 1098028

4 files changed

Lines changed: 65 additions & 103 deletions

File tree

compiler/rustc_abi/src/layout.rs

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
680680

681681
return true;
682682
}
683-
// Repacking is currently only on future edition. For editions where it is disabled,
684-
// fall back to the original niche-filling behaviour.
685-
if !repr.can_repack_variant_around_niche() {
686-
return false;
687-
}
683+
688684
// The ordinary niche-filling path can only move a non-largest variant as a
689685
// whole before or after the chosen niche. If that fails, try placing the
690686
// variant's fields individually while treating the niche bytes as reserved.
@@ -764,27 +760,20 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
764760

765761
Some(layout)
766762
};
767-
if repr.can_repack_variant_around_niche() {
768-
let max_variant_size = variant_layouts.iter().map(|layout| layout.size).max()?;
769-
// Chooses the first max-sized niche-providing variant whose layout succeeds.
770-
for (largest_variant_index, _) in
771-
variant_layouts.iter_enumerated().filter(|&(_, layout)| {
772-
layout.size == max_variant_size && layout.largest_niche.is_some()
773-
})
774-
{
775-
if let Some(layout) = try_niche_variant(largest_variant_index) {
776-
return Some(layout);
777-
}
778-
}
779763

780-
None
781-
} else {
782-
let largest_variant_index = variant_layouts
783-
.iter_enumerated()
784-
.max_by_key(|(_i, layout)| layout.size.bytes())
785-
.map(|(i, _layout)| i)?;
786-
try_niche_variant(largest_variant_index)
764+
let max_variant_size = variant_layouts.iter().map(|layout| layout.size).max()?;
765+
// Chooses the first max-sized niche-providing variant whose layout succeeds.
766+
for (largest_variant_index, _) in
767+
variant_layouts.iter_enumerated().filter(|&(_, layout)| {
768+
layout.size == max_variant_size && layout.largest_niche.is_some()
769+
})
770+
{
771+
if let Some(layout) = try_niche_variant(largest_variant_index) {
772+
return Some(layout);
773+
}
787774
}
775+
776+
None
788777
};
789778

790779
let niche_filling_layout = calculate_niche_filling_layout();

compiler/rustc_abi/src/lib.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ bitflags! {
9494
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
9595
const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS = 1 << 5;
9696
const IS_SCALABLE = 1 << 6;
97-
/// If true, enum niche-filling may repack variant fields around the reserved niche.
98-
const CAN_REPACK_VARIANT_AROUND_NICHE = 1 << 7;
99-
// Any of these flags being set prevent field reordering optimisation.
10097
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
10198
| ReprFlags::IS_SIMD.bits()
10299
| ReprFlags::IS_SCALABLE.bits()
@@ -228,12 +225,6 @@ impl ReprOptions {
228225
!self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
229226
}
230227

231-
/// Returns `true` if enum niche-filling can try to pack variant fields around
232-
/// the reserved niche when whole-variant placement fails.
233-
pub fn can_repack_variant_around_niche(&self) -> bool {
234-
self.flags.contains(ReprFlags::CAN_REPACK_VARIANT_AROUND_NICHE)
235-
}
236-
237228
/// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
238229
pub fn inhibits_union_abi_opt(&self) -> bool {
239230
self.c()

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,10 +1603,6 @@ impl<'tcx> TyCtxt<'tcx> {
16031603
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
16041604
}
16051605

1606-
if self.def_span(did).edition().at_least_edition_future() {
1607-
flags.insert(ReprFlags::CAN_REPACK_VARIANT_AROUND_NICHE);
1608-
}
1609-
16101606
// box is special, on the one hand the compiler assumes an ordered layout, with the pointer
16111607
// always at offset zero. On the other hand we want scalar abi optimizations.
16121608
let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox);
Lines changed: 52 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
//@ revisions: old future
21
//@ run-pass
3-
//@ [old] edition:2024
4-
//@ [future] edition:future
5-
//@ [future] compile-flags: -Z unstable-options
62

73
#![allow(dead_code)]
8-
#![cfg_attr(future, feature(offset_of_enum))]
4+
#![feature(offset_of_enum)]
95

10-
#[cfg(future)]
116
use std::mem::{align_of, offset_of};
127
use std::mem::size_of;
138
use std::num::NonZero;
@@ -77,64 +72,55 @@ enum ChooseFittingNiche {
7772
fn main() {
7873
assert_eq!(size_of::<Inner>(), 8);
7974

80-
#[cfg(old)]
81-
{
82-
assert_eq!(size_of::<Outer>(), 12);
83-
assert_eq!(size_of::<RepackPadding>(), 12);
84-
}
85-
86-
#[cfg(future)]
87-
{
88-
assert_eq!(size_of::<Outer>(), 8);
89-
assert_eq!(size_of::<RepackPadding>(), 8);
90-
91-
assert_eq!(size_of::<RepackedBase>(), 8);
92-
assert_eq!(align_of::<RepackedBase>(), 4);
93-
assert_eq!(offset_of!(RepackedBase, int32), 0);
94-
assert_eq!(offset_of!(RepackedBase, boolean), 4);
95-
96-
assert_eq!(size_of::<RepackedAroundNiche>(), 8);
97-
assert_eq!(align_of::<RepackedAroundNiche>(), 4);
98-
assert_eq!(size_of::<Option<RepackedAroundNiche>>(), 8);
99-
assert_eq!(offset_of!(RepackedAroundNiche, A.0), 0);
100-
assert_eq!(offset_of!(RepackedAroundNiche, B.1), 0);
101-
assert_eq!(offset_of!(RepackedAroundNiche, B.2), 5);
102-
assert_eq!(offset_of!(RepackedAroundNiche, B.0), 6);
103-
104-
assert_eq!(size_of::<NestedRepackedAroundNiche>(), 8);
105-
assert_eq!(align_of::<NestedRepackedAroundNiche>(), 4);
106-
assert_eq!(size_of::<Option<NestedRepackedAroundNiche>>(), 8);
107-
assert_eq!(offset_of!(NestedRepackedAroundNiche, A.0), 0);
108-
assert_eq!(offset_of!(NestedRepackedAroundNiche, B.1), 0);
109-
assert_eq!(offset_of!(NestedRepackedAroundNiche, B.2), 5);
110-
assert_eq!(offset_of!(NestedRepackedAroundNiche, B.0), 6);
111-
112-
assert_eq!(size_of::<RepackedPair>(), 4);
113-
assert_eq!(align_of::<RepackedPair>(), 2);
114-
assert_eq!(offset_of!(RepackedPair, field2), 0);
115-
assert_eq!(offset_of!(RepackedPair, field3), 2);
116-
117-
assert_eq!(size_of::<RepackedNestedAggregate>(), 8);
118-
assert_eq!(align_of::<RepackedNestedAggregate>(), 4);
119-
assert_eq!(size_of::<Option<RepackedNestedAggregate>>(), 8);
120-
assert_eq!(offset_of!(RepackedNestedAggregate, B.0), 0);
121-
assert_eq!(offset_of!(RepackedNestedAggregate, A.1), 0);
122-
assert_eq!(offset_of!(RepackedNestedAggregate, A.0), 6);
123-
124-
assert_eq!(size_of::<FittingNichePayload>(), 8);
125-
assert_eq!(align_of::<FittingNichePayload>(), 4);
126-
assert_eq!(offset_of!(FittingNichePayload, word), 0);
127-
assert_eq!(offset_of!(FittingNichePayload, flag), 4);
128-
129-
assert_eq!(size_of::<ChooseFittingNiche>(), 8);
130-
assert_eq!(align_of::<ChooseFittingNiche>(), 4);
131-
assert_eq!(size_of::<Option<ChooseFittingNiche>>(), 8);
132-
assert_eq!(offset_of!(ChooseFittingNiche, WideNiche.0), 0);
133-
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheFront.1), 0);
134-
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheFront.2), 5);
135-
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheFront.0), 6);
136-
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheBack.1), 0);
137-
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheBack.2), 5);
138-
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheBack.0), 6);
139-
}
75+
assert_eq!(size_of::<Outer>(), 8);
76+
assert_eq!(size_of::<RepackPadding>(), 8);
77+
78+
assert_eq!(size_of::<RepackedBase>(), 8);
79+
assert_eq!(align_of::<RepackedBase>(), 4);
80+
assert_eq!(offset_of!(RepackedBase, int32), 0);
81+
assert_eq!(offset_of!(RepackedBase, boolean), 4);
82+
83+
assert_eq!(size_of::<RepackedAroundNiche>(), 8);
84+
assert_eq!(align_of::<RepackedAroundNiche>(), 4);
85+
assert_eq!(size_of::<Option<RepackedAroundNiche>>(), 8);
86+
assert_eq!(offset_of!(RepackedAroundNiche, A.0), 0);
87+
assert_eq!(offset_of!(RepackedAroundNiche, B.1), 0);
88+
assert_eq!(offset_of!(RepackedAroundNiche, B.2), 5);
89+
assert_eq!(offset_of!(RepackedAroundNiche, B.0), 6);
90+
91+
assert_eq!(size_of::<NestedRepackedAroundNiche>(), 8);
92+
assert_eq!(align_of::<NestedRepackedAroundNiche>(), 4);
93+
assert_eq!(size_of::<Option<NestedRepackedAroundNiche>>(), 8);
94+
assert_eq!(offset_of!(NestedRepackedAroundNiche, A.0), 0);
95+
assert_eq!(offset_of!(NestedRepackedAroundNiche, B.1), 0);
96+
assert_eq!(offset_of!(NestedRepackedAroundNiche, B.2), 5);
97+
assert_eq!(offset_of!(NestedRepackedAroundNiche, B.0), 6);
98+
99+
assert_eq!(size_of::<RepackedPair>(), 4);
100+
assert_eq!(align_of::<RepackedPair>(), 2);
101+
assert_eq!(offset_of!(RepackedPair, field2), 0);
102+
assert_eq!(offset_of!(RepackedPair, field3), 2);
103+
104+
assert_eq!(size_of::<RepackedNestedAggregate>(), 8);
105+
assert_eq!(align_of::<RepackedNestedAggregate>(), 4);
106+
assert_eq!(size_of::<Option<RepackedNestedAggregate>>(), 8);
107+
assert_eq!(offset_of!(RepackedNestedAggregate, B.0), 0);
108+
assert_eq!(offset_of!(RepackedNestedAggregate, A.1), 0);
109+
assert_eq!(offset_of!(RepackedNestedAggregate, A.0), 6);
110+
111+
assert_eq!(size_of::<FittingNichePayload>(), 8);
112+
assert_eq!(align_of::<FittingNichePayload>(), 4);
113+
assert_eq!(offset_of!(FittingNichePayload, word), 0);
114+
assert_eq!(offset_of!(FittingNichePayload, flag), 4);
115+
116+
assert_eq!(size_of::<ChooseFittingNiche>(), 8);
117+
assert_eq!(align_of::<ChooseFittingNiche>(), 4);
118+
assert_eq!(size_of::<Option<ChooseFittingNiche>>(), 8);
119+
assert_eq!(offset_of!(ChooseFittingNiche, WideNiche.0), 0);
120+
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheFront.1), 0);
121+
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheFront.2), 5);
122+
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheFront.0), 6);
123+
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheBack.1), 0);
124+
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheBack.2), 5);
125+
assert_eq!(offset_of!(ChooseFittingNiche, SmallNicheBack.0), 6);
140126
}

0 commit comments

Comments
 (0)