@@ -232,7 +232,7 @@ enum StructKind {
232
232
/// A univariant, the last field of which may be coerced to unsized.
233
233
MaybeUnsized ,
234
234
/// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
235
- Prefixed ( Size , Align ) ,
235
+ Prefixed ( MemoryPosition ) ,
236
236
}
237
237
238
238
// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
@@ -291,7 +291,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
291
291
bug ! ( "struct cannot be packed and aligned" ) ;
292
292
}
293
293
294
- let mut align = if pack. is_some ( ) {
294
+ let base_align = if pack. is_some ( ) {
295
295
dl. i8_align
296
296
} else {
297
297
dl. aggregate_align
@@ -302,8 +302,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
302
302
let mut inverse_memory_index: Vec < u32 > = ( 0 ..fields. len ( ) as u32 ) . collect ( ) ;
303
303
304
304
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 ;
307
307
}
308
308
309
309
if optimize {
@@ -344,18 +344,17 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
344
344
// produce `memory_index` (see `invert_mapping`).
345
345
346
346
347
- let mut offset = Size :: ZERO ;
347
+ let mut offset_pos = LayoutPositionPref :: new ( Size :: ZERO , base_align ) ;
348
348
let mut largest_niche = None ;
349
349
let mut largest_niche_available = 0 ;
350
350
351
- if let StructKind :: Prefixed ( prefix_size , prefix_align ) = kind {
351
+ if let StructKind :: Prefixed ( prefix_mem_pos ) = kind {
352
352
let prefix_align = if let Some ( pack) = pack {
353
- prefix_align . min ( pack)
353
+ prefix_mem_pos . align . min ( pack)
354
354
} else {
355
- prefix_align
355
+ prefix_mem_pos . align
356
356
} ;
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 ( ) ;
359
358
}
360
359
361
360
for & i in & inverse_memory_index {
@@ -369,37 +368,35 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
369
368
sized = false ;
370
369
}
371
370
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) )
375
374
} else {
376
- field. pref_pos . align
375
+ field. pref_pos
377
376
} ;
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 ) ;
380
378
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 ;
383
381
384
382
if let Some ( mut niche) = field. largest_niche . clone ( ) {
385
383
let available = niche. available ( dl) ;
386
384
if available > largest_niche_available {
387
385
largest_niche_available = available;
388
- niche. offset += offset ;
386
+ niche. offset += offset_pos . size ;
389
387
largest_niche = Some ( niche) ;
390
388
}
391
389
}
392
390
393
- offset = offset . checked_add ( field . pref_pos . size , dl)
391
+ offset_pos = offset_pos . checked_add ( field_pos , dl)
394
392
. ok_or ( LayoutError :: SizeOverflow ( ty) ) ?;
395
393
}
396
394
397
395
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) ) ;
399
397
}
400
398
401
- debug ! ( "univariant min_size: {:?}" , offset) ;
402
- let min_size = offset;
399
+ debug ! ( "univariant min_size: {:?}" , offset_pos. size) ;
403
400
404
401
// As stated above, inverse_memory_index holds field indices by increasing offset.
405
402
// This makes it an already-sorted view of the offsets vec.
@@ -415,11 +412,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
415
412
memory_index = inverse_memory_index;
416
413
}
417
414
418
- let size = min_size. align_to ( align. abi ) ;
415
+ // preserve stride == size
416
+ let pref_pos = offset_pos. strided ( ) ;
419
417
let mut abi = Abi :: Aggregate { sized } ;
420
418
421
419
// Unpack newtype ABIs and find scalar pairs.
422
- if sized && size. bytes ( ) > 0 {
420
+ if sized && pref_pos . size . bytes ( ) > 0 {
423
421
// All other fields must be ZSTs, and we need them to all start at 0.
424
422
let mut zst_offsets =
425
423
offsets. iter ( ) . enumerate ( ) . filter ( |& ( i, _) | fields[ i] . is_zst ( ) ) ;
@@ -432,8 +430,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
432
430
( Some ( ( i, field) ) , None , None ) => {
433
431
// Field fills the struct and it has a scalar or scalar pair ABI.
434
432
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 {
437
435
match field. abi {
438
436
// For plain scalars, or vectors of them, we can't unpack
439
437
// newtypes for `#[repr(C)]`, as that affects C ABIs.
@@ -475,8 +473,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
475
473
} ;
476
474
if offsets[ i] == pair_offsets[ 0 ] &&
477
475
offsets[ j] == pair_offsets[ 1 ] &&
478
- align == pair. pref_pos . align &&
479
- size == pair. pref_pos . size {
476
+ pref_pos == pair. pref_pos {
480
477
// We can use `ScalarPair` only when it matches our
481
478
// already computed layout (including `#[repr(C)]`).
482
479
abi = pair. abi ;
@@ -492,8 +489,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
492
489
abi = Abi :: Uninhabited ;
493
490
}
494
491
495
- let pref_pos = LayoutPositionPref :: new ( size, align) ;
496
-
497
492
Ok ( LayoutDetails {
498
493
variants : Variants :: Single { index : VariantIdx :: new ( 0 ) } ,
499
494
fields : FieldPlacement :: Arbitrary {
@@ -1080,10 +1075,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1080
1075
}
1081
1076
}
1082
1077
1078
+ let prefix_mem_pos = MemoryPosition :: new ( min_ity. size ( ) , prefix_align) ;
1079
+
1083
1080
// Create the set of structs that represent each variant.
1084
1081
let mut layout_variants = variants. iter_enumerated ( ) . map ( |( i, field_layouts) | {
1085
1082
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 ) ) ?;
1087
1084
st. variants = Variants :: Single { index : i } ;
1088
1085
// Find the first field we can't move later
1089
1086
// to make room for a larger discriminant.
@@ -1451,8 +1448,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1451
1448
StructKind :: AlwaysSized ,
1452
1449
) ?;
1453
1450
1454
- let prefix_pref_pos = prefix. pref_pos ;
1455
-
1456
1451
// Split the prefix layout into the "outer" fields (upvars and
1457
1452
// discriminant) and the "promoted" fields. Promoted fields will
1458
1453
// get included in each variant that requested them in
@@ -1491,6 +1486,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1491
1486
} ;
1492
1487
1493
1488
let mut pref_pos = prefix. pref_pos ;
1489
+ let prefix_mem_pos = pref_pos. mem_pos ( ) ;
1494
1490
let variants = info. variant_fields . iter_enumerated ( ) . map ( |( index, variant_fields) | {
1495
1491
// Only include overlap-eligible fields when we compute our variant layout.
1496
1492
let variant_only_tys = variant_fields
@@ -1511,7 +1507,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1511
1507
. map ( |ty| self . layout_of ( ty) )
1512
1508
. collect :: < Result < Vec < _ > , _ > > ( ) ?,
1513
1509
& ReprOptions :: default ( ) ,
1514
- StructKind :: Prefixed ( prefix_pref_pos . size , prefix_pref_pos . align . abi ) ) ?;
1510
+ StructKind :: Prefixed ( prefix_mem_pos ) ) ?;
1515
1511
variant. variants = Variants :: Single { index } ;
1516
1512
1517
1513
let ( offsets, memory_index) = match variant. fields {
0 commit comments