@@ -1418,11 +1418,15 @@ enum SavedLocalEligibility {
1418
1418
// Also included in the layout are the upvars and the discriminant.
1419
1419
// These are included as fields on the "outer" layout; they are not part
1420
1420
// of any variant.
1421
+ // TODO: change documentation
1421
1422
impl < ' tcx > LayoutCx < ' tcx , TyCtxt < ' tcx > > {
1422
1423
/// Compute the eligibility and assignment of each local.
1424
+ /// Saved locals corresponding to upvars will not be returned in the return value, as they are
1425
+ /// already stored (saved) in the generator implicitly.
1423
1426
fn generator_saved_local_eligibility (
1424
1427
& self ,
1425
1428
info : & GeneratorLayout < ' tcx > ,
1429
+ upvar_count : usize ,
1426
1430
) -> ( BitSet < GeneratorSavedLocal > , IndexVec < GeneratorSavedLocal , SavedLocalEligibility > ) {
1427
1431
use SavedLocalEligibility :: * ;
1428
1432
@@ -1498,7 +1502,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1498
1502
let mut used_variants = BitSet :: new_empty ( info. variant_fields . len ( ) ) ;
1499
1503
for assignment in & assignments {
1500
1504
if let Assigned ( idx) = assignment {
1501
- used_variants. insert ( * idx) ;
1505
+ if * idx != VariantIdx :: new ( 0 ) {
1506
+ used_variants. insert ( * idx) ;
1507
+ }
1502
1508
}
1503
1509
}
1504
1510
if used_variants. count ( ) < 2 {
@@ -1511,8 +1517,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1511
1517
1512
1518
// Write down the order of our locals that will be promoted to the prefix.
1513
1519
{
1520
+ for upvar in 0 ..upvar_count {
1521
+ let local = GeneratorSavedLocal :: new ( upvar) ;
1522
+ ineligible_locals. remove ( local) ;
1523
+ assignments[ local] = Ineligible ( Some ( upvar as u32 ) ) ;
1524
+ }
1514
1525
for ( idx, local) in ineligible_locals. iter ( ) . enumerate ( ) {
1515
- assignments[ local] = Ineligible ( Some ( idx as u32 ) ) ;
1526
+ // Skip over tag and upvars
1527
+ assignments[ local] = Ineligible ( Some ( ( upvar_count + 1 + idx) as u32 ) ) ;
1516
1528
}
1517
1529
}
1518
1530
debug ! ( "generator saved local assignments: {:?}" , assignments) ;
@@ -1535,12 +1547,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1535
1547
None => return Err ( LayoutError :: Unknown ( ty) ) ,
1536
1548
Some ( info) => info,
1537
1549
} ;
1538
- let ( ineligible_locals, assignments) = self . generator_saved_local_eligibility ( & info) ;
1550
+ let upvar_count = substs. as_generator ( ) . prefix_tys ( ) . count ( ) ;
1551
+
1552
+ let ( ineligible_locals, assignments) =
1553
+ self . generator_saved_local_eligibility ( & info, upvar_count) ;
1539
1554
1540
1555
// Build a prefix layout, including "promoting" all ineligible
1541
1556
// locals as part of the prefix. We compute the layout of all of
1542
1557
// these fields at once to get optimal packing.
1543
- let tag_index = substs . as_generator ( ) . prefix_tys ( ) . count ( ) ;
1558
+ let tag_index = upvar_count ;
1544
1559
1545
1560
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
1546
1561
let max_discr = ( info. variant_fields . len ( ) - 1 ) as u128 ;
@@ -1558,6 +1573,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1558
1573
. map ( |local| subst_field ( info. field_tys [ local] ) )
1559
1574
. map ( |ty| tcx. mk_maybe_uninit ( ty) )
1560
1575
. map ( |ty| self . layout_of ( ty) ) ;
1576
+
1577
+ // The upvars are stored at the beginning of the generators
1578
+ // They are also included in the 0th (unresumed) variant
1579
+ // The promoted locals are placed directly after the upvars.
1580
+ // Because of this the rest of the code can handle upvars and promoted locals in a generic
1581
+ // way.
1561
1582
let prefix_layouts = substs
1562
1583
. as_generator ( )
1563
1584
. prefix_tys ( )
@@ -1580,35 +1601,57 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1580
1601
// GeneratorLayout.
1581
1602
debug ! ( "prefix = {:#?}" , prefix) ;
1582
1603
let ( outer_fields, promoted_offsets, promoted_memory_index) = match prefix. fields {
1583
- FieldsShape :: Arbitrary { mut offsets, memory_index } => {
1584
- let mut inverse_memory_index = invert_mapping ( & memory_index) ;
1585
-
1586
- // "a" (`0..b_start`) and "b" (`b_start..`) correspond to
1587
- // "outer" and "promoted" fields respectively.
1588
- let b_start = ( tag_index + 1 ) as u32 ;
1589
- let offsets_b = offsets. split_off ( b_start as usize ) ;
1590
- let offsets_a = offsets;
1591
-
1592
- // Disentangle the "a" and "b" components of `inverse_memory_index`
1593
- // by preserving the order but keeping only one disjoint "half" each.
1594
- // FIXME(eddyb) build a better abstraction for permutations, if possible.
1595
- let inverse_memory_index_b: Vec < _ > =
1596
- inverse_memory_index. iter ( ) . filter_map ( |& i| i. checked_sub ( b_start) ) . collect ( ) ;
1597
- inverse_memory_index. retain ( |& i| i < b_start) ;
1598
- let inverse_memory_index_a = inverse_memory_index;
1599
-
1600
- // Since `inverse_memory_index_{a,b}` each only refer to their
1604
+ FieldsShape :: Arbitrary { offsets, memory_index } => {
1605
+ let inverse_memory_index = invert_mapping ( & memory_index) ;
1606
+
1607
+ // Outer fields - upvars and tag
1608
+ let after_tag = tag_index + 1 ;
1609
+ let offsets_outer: Vec < _ > = offsets. iter ( ) . take ( after_tag) . cloned ( ) . collect ( ) ;
1610
+ let mut inverse_memory_index_outer = inverse_memory_index. clone ( ) ;
1611
+ inverse_memory_index_outer. retain ( |& i| i < after_tag as u32 ) ;
1612
+
1613
+ // Promoted fields - upvars and promoted locals
1614
+ let offsets_promoted = offsets;
1615
+ let inverse_memory_index_promoted = inverse_memory_index;
1616
+ /*let mut offsets_promoted = offsets;
1617
+ offsets_promoted.remove(tag_index);
1618
+ // Keep indices lower than tag, remove tag, and lower indices higher than tag
1619
+ let tag_source_index = inverse_memory_index[tag_index];
1620
+ let inverse_memory_index_promoted: Vec<_> = inverse_memory_index
1621
+ .into_iter()
1622
+ .filter_map(|source_index| {
1623
+ if source_index != tag_source_index {
1624
+ if source_index >= tag_source_index {
1625
+ Some(source_index - 1)
1626
+ } else {
1627
+ Some(source_index)
1628
+ }
1629
+ } else {
1630
+ None
1631
+ }
1632
+ })
1633
+ .collect();*/
1634
+
1635
+ // Since `inverse_memory_index_{outer,promoted}` each only refer to their
1601
1636
// respective fields, they can be safely inverted
1602
- let memory_index_a = invert_mapping ( & inverse_memory_index_a ) ;
1603
- let memory_index_b = invert_mapping ( & inverse_memory_index_b ) ;
1637
+ let memory_index_outer = invert_mapping ( & inverse_memory_index_outer ) ;
1638
+ let memory_index_promoted = invert_mapping ( & inverse_memory_index_promoted ) ;
1604
1639
1605
- let outer_fields =
1606
- FieldsShape :: Arbitrary { offsets : offsets_a, memory_index : memory_index_a } ;
1607
- ( outer_fields, offsets_b, memory_index_b)
1640
+ let outer_fields = FieldsShape :: Arbitrary {
1641
+ offsets : offsets_outer,
1642
+ memory_index : memory_index_outer,
1643
+ } ;
1644
+ ( outer_fields, offsets_promoted, memory_index_promoted)
1608
1645
}
1609
1646
_ => bug ! ( ) ,
1610
1647
} ;
1611
1648
1649
+ for ( index, layout) in prefix_layouts. iter ( ) . enumerate ( ) {
1650
+ info ! ( "LAYOUT, prefix_layout_{}={:#?}" , index, layout) ;
1651
+ }
1652
+ info ! ( "LAYOUT, tag_index={:?}, upvar_count={:?}, prefix_layouts.len()={:?}, prefix_size={:?}" , tag_index, upvar_count, prefix_layouts. len( ) , prefix_size) ;
1653
+ info ! ( "LAYOUT, outer_fields={:#?}, promoted_offsets={:#?}, promoted_memory_index={:#?}" , outer_fields, promoted_offsets, promoted_memory_index) ;
1654
+
1612
1655
let mut size = prefix. size ;
1613
1656
let mut align = prefix. align ;
1614
1657
let variants = info
@@ -1626,11 +1669,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1626
1669
} )
1627
1670
. map ( |local| subst_field ( info. field_tys [ * local] ) ) ;
1628
1671
1672
+ let x = variant_only_tys
1673
+ . map ( |ty| self . layout_of ( ty) )
1674
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1675
+ info ! ( "VARIANT, index={:?}, variant_only_tys={:#?}" , index, x) ;
1676
+
1629
1677
let mut variant = self . univariant_uninterned (
1630
1678
ty,
1631
- & variant_only_tys
1632
- . map ( |ty| self . layout_of ( ty) )
1633
- . collect :: < Result < Vec < _ > , _ > > ( ) ?,
1679
+ & x,
1634
1680
& ReprOptions :: default ( ) ,
1635
1681
StructKind :: Prefixed ( prefix_size, prefix_align. abi ) ,
1636
1682
) ?;
@@ -1713,7 +1759,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1713
1759
size,
1714
1760
align,
1715
1761
} ) ;
1716
- debug ! ( "generator layout ({:?}): {:#?}" , ty, layout) ;
1762
+ info ! ( "generator layout ({:?}): {:#?}" , ty, layout) ;
1717
1763
Ok ( layout)
1718
1764
}
1719
1765
0 commit comments