@@ -1311,10 +1311,19 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13111311 ) -> Result < & ' tcx LayoutDetails , LayoutError < ' tcx > > {
13121312 use SavedLocalEligibility :: * ;
13131313 let tcx = self . tcx ;
1314- let recompute_memory_index = |offsets : & [ Size ] | -> Vec < u32 > {
1314+ let recompute_memory_index = |offsets : & [ Size ] , fields : & [ TyLayout < ' _ > ] | -> Vec < u32 > {
13151315 debug ! ( "recompute_memory_index({:?})" , offsets) ;
1316+ debug ! ( "fields = {:#?}" , fields) ;
13161317 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+ } ) ;
13181327
13191328 let mut index = vec ! [ 0 ; offsets. len( ) ] ;
13201329 for i in 0 ..index. len ( ) {
@@ -1337,9 +1346,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13371346 let prefix_tys = substs. prefix_tys ( def_id, tcx)
13381347 . chain ( iter:: once ( substs. discr_ty ( tcx) ) )
13391348 . chain ( promoted_tys) ;
1349+ let prefix_layouts = prefix_tys
1350+ . map ( |ty| self . layout_of ( ty) )
1351+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
13401352 let prefix = self . univariant_uninterned (
13411353 ty,
1342- & prefix_tys . map ( |ty| self . layout_of ( ty ) ) . collect :: < Result < Vec < _ > , _ > > ( ) ? ,
1354+ & prefix_layouts ,
13431355 & ReprOptions :: default ( ) ,
13441356 StructKind :: AlwaysSized ) ?;
13451357 let ( prefix_size, prefix_align) = ( prefix. size , prefix. align ) ;
@@ -1354,7 +1366,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13541366 let offsets_b = offsets. split_off ( discr_index + 1 ) ;
13551367 let offsets_a = offsets;
13561368
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+
13581374 let outer_fields = FieldPlacement :: Arbitrary { offsets : offsets_a, memory_index } ;
13591375 ( outer_fields, offsets_b)
13601376 }
@@ -1364,24 +1380,29 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13641380 let mut size = prefix. size ;
13651381 let mut align = prefix. align ;
13661382 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+ }
13791402
13801403 let mut variant = self . univariant_uninterned (
13811404 ty,
1382- & variant_only_tys
1383- . map ( |ty| self . layout_of ( ty) )
1384- . collect :: < Result < Vec < _ > , _ > > ( ) ?,
1405+ & variant_only_layouts,
13851406 & ReprOptions :: default ( ) ,
13861407 StructKind :: Prefixed ( prefix_size, prefix_align. abi ) ) ?;
13871408 variant. variants = Variants :: Single { index } ;
@@ -1408,7 +1429,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14081429 }
14091430 }
14101431 }
1411- let memory_index = recompute_memory_index ( & combined_offsets) ;
1432+ let memory_index = recompute_memory_index ( & combined_offsets, & variant_layouts ) ;
14121433 variant. fields = FieldPlacement :: Arbitrary { offsets : combined_offsets, memory_index } ;
14131434
14141435 size = size. max ( variant. size ) ;
@@ -1442,7 +1463,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14421463 debug ! ( "generator layout ({:?}): {:#?}" , ty, layout) ;
14431464 Ok ( layout)
14441465 }
1466+ }
14451467
1468+ impl < ' tcx > LayoutCx < ' tcx , TyCtxt < ' tcx > > {
14461469 /// This is invoked by the `layout_raw` query to record the final
14471470 /// layout of each type.
14481471 #[ inline( always) ]
0 commit comments