@@ -1311,10 +1311,19 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1311
1311
) -> Result < & ' tcx LayoutDetails , LayoutError < ' tcx > > {
1312
1312
use SavedLocalEligibility :: * ;
1313
1313
let tcx = self . tcx ;
1314
- let recompute_memory_index = |offsets : & [ Size ] | -> Vec < u32 > {
1314
+ let recompute_memory_index = |offsets : & [ Size ] , fields : & [ TyLayout < ' _ > ] | -> Vec < u32 > {
1315
1315
debug ! ( "recompute_memory_index({:?})" , offsets) ;
1316
+ debug ! ( "fields = {:#?}" , fields) ;
1316
1317
let mut inverse_index = ( 0 ..offsets. len ( ) as u32 ) . collect :: < Vec < _ > > ( ) ;
1317
- inverse_index. sort_unstable_by_key ( |i| offsets[ * i as usize ] ) ;
1318
+ inverse_index. sort_unstable_by_key ( |i| {
1319
+ // Place ZSTs before other fields at the same offset so all fields are
1320
+ // in order by offset. Codegen expects this.
1321
+ //
1322
+ // In generators we can have ZST fields with nonzero offsets (these are
1323
+ // fields specific to one variant that come after the prefix).
1324
+ let zst = fields[ * i as usize ] . is_zst ( ) ;
1325
+ ( offsets[ * i as usize ] , !zst)
1326
+ } ) ;
1318
1327
1319
1328
let mut index = vec ! [ 0 ; offsets. len( ) ] ;
1320
1329
for i in 0 ..index. len ( ) {
@@ -1337,9 +1346,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1337
1346
let prefix_tys = substs. prefix_tys ( def_id, tcx)
1338
1347
. chain ( iter:: once ( substs. discr_ty ( tcx) ) )
1339
1348
. chain ( promoted_tys) ;
1349
+ let prefix_layouts = prefix_tys
1350
+ . map ( |ty| self . layout_of ( ty) )
1351
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1340
1352
let prefix = self . univariant_uninterned (
1341
1353
ty,
1342
- & prefix_tys . map ( |ty| self . layout_of ( ty ) ) . collect :: < Result < Vec < _ > , _ > > ( ) ? ,
1354
+ & prefix_layouts ,
1343
1355
& ReprOptions :: default ( ) ,
1344
1356
StructKind :: AlwaysSized ) ?;
1345
1357
let ( prefix_size, prefix_align) = ( prefix. size , prefix. align ) ;
@@ -1354,7 +1366,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1354
1366
let offsets_b = offsets. split_off ( discr_index + 1 ) ;
1355
1367
let offsets_a = offsets;
1356
1368
1357
- let memory_index = recompute_memory_index ( & offsets_a) ;
1369
+ // Okay to use `prefix_layouts` here since we're accessing
1370
+ // fields (0..discr_index + 1); the field indices will be the
1371
+ // same.
1372
+ let memory_index = recompute_memory_index ( & offsets_a, & prefix_layouts) ;
1373
+
1358
1374
let outer_fields = FieldPlacement :: Arbitrary { offsets : offsets_a, memory_index } ;
1359
1375
( outer_fields, offsets_b)
1360
1376
}
@@ -1364,24 +1380,29 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1364
1380
let mut size = prefix. size ;
1365
1381
let mut align = prefix. align ;
1366
1382
let variants = info. variant_fields . iter_enumerated ( ) . map ( |( index, variant_fields) | {
1367
- // Only include overlap-eligible fields when we compute our variant layout.
1368
- let variant_only_tys = variant_fields
1369
- . iter ( )
1370
- . filter ( |local| {
1371
- match assignments[ * * local] {
1372
- Unassigned => bug ! ( ) ,
1373
- Assigned ( v) if v == index => true ,
1374
- Assigned ( _) => bug ! ( "assignment does not match variant" ) ,
1375
- Ineligible ( _) => false ,
1376
- }
1377
- } )
1378
- . map ( |local| subst_field ( info. field_tys [ * local] ) ) ;
1383
+ let mut variant_layouts = Vec :: with_capacity ( variant_fields. len ( ) ) ;
1384
+ let mut variant_only_layouts = Vec :: with_capacity ( variant_fields. len ( ) ) ;
1385
+ for local in variant_fields {
1386
+ let ty = subst_field ( info. field_tys [ * local] ) ;
1387
+ let layout = self . layout_of ( ty) ?;
1388
+
1389
+ variant_layouts. push ( layout) ;
1390
+
1391
+ // Only include overlap-eligible fields when we compute our variant layout.
1392
+ let variant_only = match assignments[ * local] {
1393
+ Unassigned => bug ! ( ) ,
1394
+ Assigned ( v) if v == index => true ,
1395
+ Assigned ( _) => bug ! ( "assignment does not match variant" ) ,
1396
+ Ineligible ( _) => false ,
1397
+ } ;
1398
+ if variant_only {
1399
+ variant_only_layouts. push ( layout) ;
1400
+ }
1401
+ }
1379
1402
1380
1403
let mut variant = self . univariant_uninterned (
1381
1404
ty,
1382
- & variant_only_tys
1383
- . map ( |ty| self . layout_of ( ty) )
1384
- . collect :: < Result < Vec < _ > , _ > > ( ) ?,
1405
+ & variant_only_layouts,
1385
1406
& ReprOptions :: default ( ) ,
1386
1407
StructKind :: Prefixed ( prefix_size, prefix_align. abi ) ) ?;
1387
1408
variant. variants = Variants :: Single { index } ;
@@ -1408,7 +1429,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1408
1429
}
1409
1430
}
1410
1431
}
1411
- let memory_index = recompute_memory_index ( & combined_offsets) ;
1432
+ let memory_index = recompute_memory_index ( & combined_offsets, & variant_layouts ) ;
1412
1433
variant. fields = FieldPlacement :: Arbitrary { offsets : combined_offsets, memory_index } ;
1413
1434
1414
1435
size = size. max ( variant. size ) ;
@@ -1442,7 +1463,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1442
1463
debug ! ( "generator layout ({:?}): {:#?}" , ty, layout) ;
1443
1464
Ok ( layout)
1444
1465
}
1466
+ }
1445
1467
1468
+ impl < ' tcx > LayoutCx < ' tcx , TyCtxt < ' tcx > > {
1446
1469
/// This is invoked by the `layout_raw` query to record the final
1447
1470
/// layout of each type.
1448
1471
#[ inline( always) ]
0 commit comments