@@ -604,12 +604,57 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
604604 tcx. intern_layout ( unit)
605605 }
606606
607- // Tuples, generators and closures.
608607 ty:: Generator ( def_id, ref substs, _) => {
609- let tys = substs. field_tys ( def_id, tcx) ;
610- univariant ( & tys. map ( |ty| self . layout_of ( ty) ) . collect :: < Result < Vec < _ > , _ > > ( ) ?,
608+ let discr_index = substs. prefix_tys ( def_id, tcx) . count ( ) ;
609+ let prefix_tys = substs. prefix_tys ( def_id, tcx)
610+ . chain ( iter:: once ( substs. discr_ty ( tcx) ) ) ;
611+ let prefix = univariant_uninterned (
612+ & prefix_tys. map ( |ty| self . layout_of ( ty) ) . collect :: < Result < Vec < _ > , _ > > ( ) ?,
611613 & ReprOptions :: default ( ) ,
612- StructKind :: AlwaysSized ) ?
614+ StructKind :: AlwaysSized ) ?;
615+
616+ let mut size = prefix. size ;
617+ let mut align = prefix. align ;
618+ let variants_tys = substs. state_tys ( def_id, tcx) ;
619+ let variants = variants_tys. enumerate ( ) . map ( |( i, variant_tys) | {
620+ let mut variant = univariant_uninterned (
621+ & variant_tys. map ( |ty| self . layout_of ( ty) ) . collect :: < Result < Vec < _ > , _ > > ( ) ?,
622+ & ReprOptions :: default ( ) ,
623+ StructKind :: Prefixed ( prefix. size , prefix. align . abi ) ) ?;
624+
625+ variant. variants = Variants :: Single { index : VariantIdx :: new ( i) } ;
626+
627+ size = size. max ( variant. size ) ;
628+ align = align. max ( variant. align ) ;
629+
630+ Ok ( variant)
631+ } ) . collect :: < Result < IndexVec < VariantIdx , _ > , _ > > ( ) ?;
632+
633+ let abi = if prefix. abi . is_uninhabited ( ) ||
634+ variants. iter ( ) . all ( |v| v. abi . is_uninhabited ( ) ) {
635+ Abi :: Uninhabited
636+ } else {
637+ Abi :: Aggregate { sized : true }
638+ } ;
639+ let discr = match & self . layout_of ( substs. discr_ty ( tcx) ) ?. abi {
640+ Abi :: Scalar ( s) => s. clone ( ) ,
641+ _ => bug ! ( ) ,
642+ } ;
643+
644+ let layout = tcx. intern_layout ( LayoutDetails {
645+ variants : Variants :: Multiple {
646+ discr,
647+ discr_kind : DiscriminantKind :: Tag ,
648+ discr_index,
649+ variants,
650+ } ,
651+ fields : prefix. fields ,
652+ abi,
653+ size,
654+ align,
655+ } ) ;
656+ debug ! ( "generator layout: {:#?}" , layout) ;
657+ layout
613658 }
614659
615660 ty:: Closure ( def_id, ref substs) => {
@@ -1646,6 +1691,14 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
16461691
16471692 fn field ( this : TyLayout < ' tcx > , cx : & C , i : usize ) -> C :: TyLayout {
16481693 let tcx = cx. tcx ( ) ;
1694+ let handle_discriminant = |discr : & Scalar | -> C :: TyLayout {
1695+ let layout = LayoutDetails :: scalar ( cx, discr. clone ( ) ) ;
1696+ MaybeResult :: from_ok ( TyLayout {
1697+ details : tcx. intern_layout ( layout) ,
1698+ ty : discr. value . to_ty ( tcx)
1699+ } )
1700+ } ;
1701+
16491702 cx. layout_of ( match this. ty . sty {
16501703 ty:: Bool |
16511704 ty:: Char |
@@ -1720,7 +1773,19 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17201773 }
17211774
17221775 ty:: Generator ( def_id, ref substs, _) => {
1723- substs. field_tys ( def_id, tcx) . nth ( i) . unwrap ( )
1776+ match this. variants {
1777+ Variants :: Single { index } => {
1778+ substs. state_tys ( def_id, tcx)
1779+ . nth ( index. as_usize ( ) ) . unwrap ( )
1780+ . nth ( i) . unwrap ( )
1781+ }
1782+ Variants :: Multiple { ref discr, discr_index, .. } => {
1783+ if i == discr_index {
1784+ return handle_discriminant ( discr) ;
1785+ }
1786+ substs. prefix_tys ( def_id, tcx) . nth ( i) . unwrap ( )
1787+ }
1788+ }
17241789 }
17251790
17261791 ty:: Tuple ( tys) => tys[ i] ,
@@ -1740,11 +1805,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17401805 // Discriminant field for enums (where applicable).
17411806 Variants :: Multiple { ref discr, .. } => {
17421807 assert_eq ! ( i, 0 ) ;
1743- let layout = LayoutDetails :: scalar ( cx, discr. clone ( ) ) ;
1744- return MaybeResult :: from_ok ( TyLayout {
1745- details : tcx. intern_layout ( layout) ,
1746- ty : discr. value . to_ty ( tcx)
1747- } ) ;
1808+ return handle_discriminant ( discr) ;
17481809 }
17491810 }
17501811 }
0 commit comments