Skip to content

Commit 2b11f26

Browse files
committed
Auto merge of rust-lang#130508 - adwinwhite:niche-not-depend-on-order, r=the8472
Get rid of niche selection's dependence on fields's order Fixes rust-lang#125630. Use the optimal niche selection decided in `univariant()` rather than picking niche field manually. r? `@the8472`
2 parents 976487c + 937b09b commit 2b11f26

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

compiler/rustc_abi/src/layout.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -527,15 +527,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
527527
let count =
528528
(niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1;
529529

530-
// Find the field with the largest niche
531-
let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
532-
.iter()
533-
.enumerate()
534-
.filter_map(|(j, field)| Some((j, field.largest_niche?)))
535-
.max_by_key(|(_, niche)| niche.available(dl))
536-
.and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
537-
let niche_offset =
538-
niche.offset + variant_layouts[largest_variant_index].fields.offset(field_index);
530+
// Use the largest niche in the largest variant.
531+
let niche = variant_layouts[largest_variant_index].largest_niche?;
532+
let (niche_start, niche_scalar) = niche.reserve(dl, count)?;
533+
let niche_offset = niche.offset;
539534
let niche_size = niche.value.size(dl);
540535
let size = variant_layouts[largest_variant_index].size.align_to(align.abi);
541536

src/tools/miri/tests/fail/uninit/padding-enum.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ fn main() {
1717
assert!(matches!(*p.as_ptr(), E::None));
1818

1919
// Turns out the discriminant is (currently) stored
20-
// in the 2nd pointer, so the first half is padding.
20+
// in the 1st pointer, so the second half is padding.
2121
let c = &p as *const _ as *const u8;
22+
let padding_offset = mem::size_of::<&'static ()>();
2223
// Read a padding byte.
23-
let _val = *c.add(0);
24+
let _val = *c.add(padding_offset);
2425
//~^ERROR: uninitialized
2526
}
2627
}

src/tools/miri/tests/fail/uninit/padding-enum.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
22
--> tests/fail/uninit/padding-enum.rs:LL:CC
33
|
4-
LL | let _val = *c.add(0);
5-
| ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
4+
LL | let _val = *c.add(padding_offset);
5+
| ^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/ui/structs-enums/type-sizes.rs

+20
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,23 @@ struct ReorderEndNiche {
209209
b: MiddleNiche4,
210210
}
211211

212+
// We want that the niche selection doesn't depend on order of the fields. See issue #125630.
213+
pub enum NicheFieldOrder1 {
214+
A {
215+
x: NonZero<u64>,
216+
y: [NonZero<u64>; 2],
217+
},
218+
B([u64; 2]),
219+
}
220+
221+
pub enum NicheFieldOrder2 {
222+
A {
223+
y: [NonZero<u64>; 2],
224+
x: NonZero<u64>,
225+
},
226+
B([u64; 2]),
227+
}
228+
212229

213230
// standins for std types which we want to be laid out in a reasonable way
214231
struct RawVecDummy {
@@ -260,6 +277,9 @@ pub fn main() {
260277
size_of::<EnumWithMaybeUninhabitedVariant<()>>());
261278
assert_eq!(size_of::<NicheFilledEnumWithAbsentVariant>(), size_of::<&'static ()>());
262279

280+
assert_eq!(size_of::<NicheFieldOrder1>(), 24);
281+
assert_eq!(size_of::<NicheFieldOrder2>(), 24);
282+
263283
assert_eq!(size_of::<Option<Option<(bool, &())>>>(), size_of::<(bool, &())>());
264284
assert_eq!(size_of::<Option<Option<(&(), bool)>>>(), size_of::<(bool, &())>());
265285
assert_eq!(size_of::<Option<Option2<bool, &()>>>(), size_of::<(bool, &())>());

0 commit comments

Comments
 (0)