@@ -232,7 +232,7 @@ enum StructKind {
232232 /// A univariant, the last field of which may be coerced to unsized.
233233 MaybeUnsized ,
234234 /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
235- Prefixed ( Size , Align ) ,
235+ Prefixed ( MemoryPosition ) ,
236236}
237237
238238// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
@@ -291,7 +291,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
291291 bug ! ( "struct cannot be packed and aligned" ) ;
292292 }
293293
294- let mut align = if pack. is_some ( ) {
294+ let base_align = if pack. is_some ( ) {
295295 dl. i8_align
296296 } else {
297297 dl. aggregate_align
@@ -302,8 +302,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
302302 let mut inverse_memory_index: Vec < u32 > = ( 0 ..fields. len ( ) as u32 ) . collect ( ) ;
303303
304304 let mut optimize = !repr. inhibit_struct_field_reordering_opt ( ) ;
305- if let StructKind :: Prefixed ( _ , align ) = kind {
306- optimize &= align. bytes ( ) == 1 ;
305+ if let StructKind :: Prefixed ( mem_pos ) = kind {
306+ optimize &= mem_pos . align . bytes ( ) == 1 ;
307307 }
308308
309309 if optimize {
@@ -344,18 +344,17 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
344344 // produce `memory_index` (see `invert_mapping`).
345345
346346
347- let mut offset = Size :: ZERO ;
347+ let mut offset_pos = LayoutPositionPref :: new ( Size :: ZERO , base_align ) ;
348348 let mut largest_niche = None ;
349349 let mut largest_niche_available = 0 ;
350350
351- if let StructKind :: Prefixed ( prefix_size , prefix_align ) = kind {
351+ if let StructKind :: Prefixed ( prefix_mem_pos ) = kind {
352352 let prefix_align = if let Some ( pack) = pack {
353- prefix_align . min ( pack)
353+ prefix_mem_pos . align . min ( pack)
354354 } else {
355- prefix_align
355+ prefix_mem_pos . align
356356 } ;
357- align = align. max ( AbiAndPrefAlign :: new ( prefix_align) ) ;
358- offset = prefix_size. align_to ( prefix_align) ;
357+ offset_pos = prefix_mem_pos. align_and_stride_to ( prefix_align) . pref_pos ( ) ;
359358 }
360359
361360 for & i in & inverse_memory_index {
@@ -369,37 +368,35 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
369368 sized = false ;
370369 }
371370
372- // Invariant: offset < dl.obj_size_bound() <= 1<<61
373- let field_align = if let Some ( pack) = pack {
374- field. pref_pos . align . min ( AbiAndPrefAlign :: new ( pack) )
371+ // Invariant: offset_pos.size < dl.obj_size_bound() <= 1<<61
372+ let field_pos = if let Some ( pack) = pack {
373+ field. pref_pos . pack_to ( AbiAndPrefAlign :: new ( pack) )
375374 } else {
376- field. pref_pos . align
375+ field. pref_pos
377376 } ;
378- offset = offset. align_to ( field_align. abi ) ;
379- align = align. max ( field_align) ;
377+ offset_pos = offset_pos. align_and_stride_to ( field_pos. align ) ;
380378
381- debug ! ( "univariant offset: {:?} field: {:#?}" , offset , field) ;
382- offsets[ i as usize ] = offset ;
379+ debug ! ( "univariant offset: {:?} field: {:#?}" , offset_pos . size , field) ;
380+ offsets[ i as usize ] = offset_pos . size ;
383381
384382 if let Some ( mut niche) = field. largest_niche . clone ( ) {
385383 let available = niche. available ( dl) ;
386384 if available > largest_niche_available {
387385 largest_niche_available = available;
388- niche. offset += offset ;
386+ niche. offset += offset_pos . size ;
389387 largest_niche = Some ( niche) ;
390388 }
391389 }
392390
393- offset = offset . checked_add ( field . pref_pos . size , dl)
391+ offset_pos = offset_pos . checked_add ( field_pos , dl)
394392 . ok_or ( LayoutError :: SizeOverflow ( ty) ) ?;
395393 }
396394
397395 if let Some ( repr_align) = repr. align {
398- align = align . max ( AbiAndPrefAlign :: new ( repr_align) ) ;
396+ offset_pos = offset_pos . align_to ( AbiAndPrefAlign :: new ( repr_align) ) ;
399397 }
400398
401- debug ! ( "univariant min_size: {:?}" , offset) ;
402- let min_size = offset;
399+ debug ! ( "univariant min_size: {:?}" , offset_pos. size) ;
403400
404401 // As stated above, inverse_memory_index holds field indices by increasing offset.
405402 // This makes it an already-sorted view of the offsets vec.
@@ -415,11 +412,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
415412 memory_index = inverse_memory_index;
416413 }
417414
418- let size = min_size. align_to ( align. abi ) ;
415+ // preserve stride == size
416+ let pref_pos = offset_pos. strided ( ) ;
419417 let mut abi = Abi :: Aggregate { sized } ;
420418
421419 // Unpack newtype ABIs and find scalar pairs.
422- if sized && size. bytes ( ) > 0 {
420+ if sized && pref_pos . size . bytes ( ) > 0 {
423421 // All other fields must be ZSTs, and we need them to all start at 0.
424422 let mut zst_offsets =
425423 offsets. iter ( ) . enumerate ( ) . filter ( |& ( i, _) | fields[ i] . is_zst ( ) ) ;
@@ -432,8 +430,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
432430 ( Some ( ( i, field) ) , None , None ) => {
433431 // Field fills the struct and it has a scalar or scalar pair ABI.
434432 if offsets[ i] . bytes ( ) == 0 &&
435- align . abi == field. pref_pos . align . abi &&
436- size == field. pref_pos . size {
433+ pref_pos . size == field. pref_pos . size &&
434+ pref_pos . align . abi == field. pref_pos . align . abi {
437435 match field. abi {
438436 // For plain scalars, or vectors of them, we can't unpack
439437 // newtypes for `#[repr(C)]`, as that affects C ABIs.
@@ -475,8 +473,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
475473 } ;
476474 if offsets[ i] == pair_offsets[ 0 ] &&
477475 offsets[ j] == pair_offsets[ 1 ] &&
478- align == pair. pref_pos . align &&
479- size == pair. pref_pos . size {
476+ pref_pos == pair. pref_pos {
480477 // We can use `ScalarPair` only when it matches our
481478 // already computed layout (including `#[repr(C)]`).
482479 abi = pair. abi ;
@@ -492,8 +489,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
492489 abi = Abi :: Uninhabited ;
493490 }
494491
495- let pref_pos = LayoutPositionPref :: new ( size, align) ;
496-
497492 Ok ( LayoutDetails {
498493 variants : Variants :: Single { index : VariantIdx :: new ( 0 ) } ,
499494 fields : FieldPlacement :: Arbitrary {
@@ -1080,10 +1075,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
10801075 }
10811076 }
10821077
1078+ let prefix_mem_pos = MemoryPosition :: new ( min_ity. size ( ) , prefix_align) ;
1079+
10831080 // Create the set of structs that represent each variant.
10841081 let mut layout_variants = variants. iter_enumerated ( ) . map ( |( i, field_layouts) | {
10851082 let mut st = self . univariant_uninterned ( ty, & field_layouts,
1086- & def. repr , StructKind :: Prefixed ( min_ity . size ( ) , prefix_align ) ) ?;
1083+ & def. repr , StructKind :: Prefixed ( prefix_mem_pos ) ) ?;
10871084 st. variants = Variants :: Single { index : i } ;
10881085 // Find the first field we can't move later
10891086 // to make room for a larger discriminant.
@@ -1451,8 +1448,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14511448 StructKind :: AlwaysSized ,
14521449 ) ?;
14531450
1454- let prefix_pref_pos = prefix. pref_pos ;
1455-
14561451 // Split the prefix layout into the "outer" fields (upvars and
14571452 // discriminant) and the "promoted" fields. Promoted fields will
14581453 // get included in each variant that requested them in
@@ -1491,6 +1486,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14911486 } ;
14921487
14931488 let mut pref_pos = prefix. pref_pos ;
1489+ let prefix_mem_pos = pref_pos. mem_pos ( ) ;
14941490 let variants = info. variant_fields . iter_enumerated ( ) . map ( |( index, variant_fields) | {
14951491 // Only include overlap-eligible fields when we compute our variant layout.
14961492 let variant_only_tys = variant_fields
@@ -1511,7 +1507,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
15111507 . map ( |ty| self . layout_of ( ty) )
15121508 . collect :: < Result < Vec < _ > , _ > > ( ) ?,
15131509 & ReprOptions :: default ( ) ,
1514- StructKind :: Prefixed ( prefix_pref_pos . size , prefix_pref_pos . align . abi ) ) ?;
1510+ StructKind :: Prefixed ( prefix_mem_pos ) ) ?;
15151511 variant. variants = Variants :: Single { index } ;
15161512
15171513 let ( offsets, memory_index) = match variant. fields {
0 commit comments