@@ -140,8 +140,13 @@ fn univariant_uninterned<'tcx>(
140
140
let optimizing = & mut inverse_memory_index[ ..end] ;
141
141
let effective_field_align = |f : & TyAndLayout < ' _ > | {
142
142
if let Some ( pack) = pack {
143
+ // return the packed alignment in bytes
143
144
f. align . abi . min ( pack) . bytes ( )
144
145
} else {
146
+ // returns log2(effective-align).
147
+ // This is ok since `pack` applies to all fields equally.
148
+ // The calculation assumes that size is an integer multiple of align, except for ZSTs.
149
+ //
145
150
// group [u8; 4] with align-4 or [u8; 6] with align-2 fields
146
151
f. align . abi . bytes ( ) . max ( f. size . bytes ( ) ) . trailing_zeros ( ) as u64
147
152
}
@@ -165,15 +170,23 @@ fn univariant_uninterned<'tcx>(
165
170
optimizing. sort_by_key ( |& x| {
166
171
// Place ZSTs first to avoid "interesting offsets",
167
172
// especially with only one or two non-ZST fields.
173
+ // Then place largest alignments first, largest niches within an alignment group last
168
174
let f = & fields[ x as usize ] ;
169
- ( !f. is_zst ( ) , cmp:: Reverse ( effective_field_align ( f) ) )
175
+ let niche_size = f. largest_niche . map_or ( 0 , |n| n. available ( cx) ) ;
176
+ ( !f. is_zst ( ) , cmp:: Reverse ( effective_field_align ( f) ) , niche_size)
170
177
} ) ;
171
178
}
172
179
173
180
StructKind :: Prefixed ( ..) => {
174
181
// Sort in ascending alignment so that the layout stays optimal
175
- // regardless of the prefix
176
- optimizing. sort_by_key ( |& x| effective_field_align ( & fields[ x as usize ] ) ) ;
182
+ // regardless of the prefix.
183
+ // And put the largest niche in an alignment group at the end
184
+ // so it can be used as discriminant in jagged enums
185
+ optimizing. sort_by_key ( |& x| {
186
+ let f = & fields[ x as usize ] ;
187
+ let niche_size = f. largest_niche . map_or ( 0 , |n| n. available ( cx) ) ;
188
+ ( effective_field_align ( f) , niche_size)
189
+ } ) ;
177
190
}
178
191
}
179
192
0 commit comments