Skip to content

Commit 2e431c6

Browse files
compare tagged/niche-filling layout and pick the best one
1 parent b0a7fbd commit 2e431c6

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

src/librustc_middle/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#![feature(bool_to_option)]
2828
#![feature(box_patterns)]
2929
#![feature(box_syntax)]
30+
#![feature(cmp_min_max_by)]
3031
#![feature(const_fn)]
3132
#![feature(const_panic)]
3233
#![feature(const_fn_transmute)]

src/librustc_middle/ty/layout.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,21 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
12331233
size,
12341234
};
12351235

1236-
tcx.intern_layout(niche_filling_layout.unwrap_or(tagged_layout))
1236+
let best_layout = match (tagged_layout, niche_filling_layout) {
1237+
(tagged_layout, Some(niche_filling_layout)) => {
1238+
// Pick the smaller layout; otherwise,
1239+
// pick the layout with the larger niche; otherwise,
1240+
// pick tagged as it has simpler codegen.
1241+
cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| {
1242+
let niche_size =
1243+
layout.largest_niche.as_ref().map_or(0, |n| n.available(dl));
1244+
(layout.size, cmp::Reverse(niche_size))
1245+
})
1246+
}
1247+
(tagged_layout, None) => tagged_layout,
1248+
};
1249+
1250+
tcx.intern_layout(best_layout)
12371251
}
12381252

12391253
// Types with no meaningful known layout.

src/test/ui/print_type_sizes/niche-filling.stdout

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ print-type-size variant `Some`: 12 bytes
88
print-type-size field `.0`: 12 bytes
99
print-type-size variant `None`: 0 bytes
1010
print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
11+
print-type-size discriminant: 1 bytes
1112
print-type-size variant `Record`: 7 bytes
12-
print-type-size field `.val`: 4 bytes
13-
print-type-size field `.post`: 2 bytes
1413
print-type-size field `.pre`: 1 bytes
14+
print-type-size field `.post`: 2 bytes
15+
print-type-size field `.val`: 4 bytes
1516
print-type-size variant `None`: 0 bytes
16-
print-type-size end padding: 1 bytes
1717
print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
1818
print-type-size discriminant: 4 bytes
1919
print-type-size variant `Some`: 4 bytes

src/test/ui/type-sizes.rs

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![feature(never_type)]
66

77
use std::mem::size_of;
8+
use std::num::NonZeroU8;
89

910
struct t {a: u8, b: i8}
1011
struct u {a: u8, b: i8, c: u8}
@@ -102,6 +103,15 @@ enum Option2<A, B> {
102103
None
103104
}
104105

106+
pub enum CanBeNicheFilledButShouldnt {
107+
A(NonZeroU8, u32),
108+
B
109+
}
110+
pub enum AlwaysTagged {
111+
A(u8, u32),
112+
B
113+
}
114+
105115
pub fn main() {
106116
assert_eq!(size_of::<u8>(), 1 as usize);
107117
assert_eq!(size_of::<u32>(), 4 as usize);
@@ -145,4 +155,11 @@ pub fn main() {
145155
assert_eq!(size_of::<Option<Option<(&(), bool)>>>(), size_of::<(bool, &())>());
146156
assert_eq!(size_of::<Option<Option2<bool, &()>>>(), size_of::<(bool, &())>());
147157
assert_eq!(size_of::<Option<Option2<&(), bool>>>(), size_of::<(bool, &())>());
158+
159+
assert_eq!(size_of::<CanBeNicheFilledButShouldnt>(), 8);
160+
assert_eq!(size_of::<Option<CanBeNicheFilledButShouldnt>>(), 8);
161+
assert_eq!(size_of::<Option<Option<CanBeNicheFilledButShouldnt>>>(), 8);
162+
assert_eq!(size_of::<AlwaysTagged>(), 8);
163+
assert_eq!(size_of::<Option<AlwaysTagged>>(), 8);
164+
assert_eq!(size_of::<Option<Option<AlwaysTagged>>>(), 8);
148165
}

0 commit comments

Comments
 (0)