@@ -140,8 +140,13 @@ fn univariant_uninterned<'tcx>(
140140 let optimizing = & mut inverse_memory_index[ ..end] ;
141141 let effective_field_align = |f : & TyAndLayout < ' _ > | {
142142 if let Some ( pack) = pack {
143+ // return the packed alignment in bytes
143144 f. align . abi . min ( pack) . bytes ( )
144145 } 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+ //
145150 // group [u8; 4] with align-4 or [u8; 6] with align-2 fields
146151 f. align . abi . bytes ( ) . max ( f. size . bytes ( ) ) . trailing_zeros ( ) as u64
147152 }
@@ -165,15 +170,23 @@ fn univariant_uninterned<'tcx>(
165170 optimizing. sort_by_key ( |& x| {
166171 // Place ZSTs first to avoid "interesting offsets",
167172 // especially with only one or two non-ZST fields.
173+ // Then place largest alignments first, largest niches within an alignment group last
168174 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)
170177 } ) ;
171178 }
172179
173180 StructKind :: Prefixed ( ..) => {
174181 // 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+ } ) ;
177190 }
178191 }
179192
0 commit comments