@@ -22,6 +22,7 @@ use rustc::hir::CodegenFnAttrFlags;
2222use rustc:: hir:: def:: CtorKind ;
2323use rustc:: hir:: def_id:: { DefId , CrateNum , LOCAL_CRATE } ;
2424use rustc:: ich:: NodeIdHashingMode ;
25+ use rustc:: mir:: Field ;
2526use rustc:: mir:: interpret:: truncate;
2627use rustc_data_structures:: fingerprint:: Fingerprint ;
2728use rustc:: ty:: Instance ;
@@ -1306,12 +1307,15 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
13061307 }
13071308 layout:: Variants :: Multiple {
13081309 discr_kind : layout:: DiscriminantKind :: Tag ,
1310+ discr_index,
13091311 ref variants,
13101312 ..
13111313 } => {
13121314 let discriminant_info = if fallback {
1313- RegularDiscriminant ( self . discriminant_type_metadata
1314- . expect ( "" ) )
1315+ RegularDiscriminant {
1316+ discr_field : Field :: from ( discr_index) ,
1317+ discr_type_metadata : self . discriminant_type_metadata . unwrap ( )
1318+ }
13151319 } else {
13161320 // This doesn't matter in this case.
13171321 NoDiscriminant
@@ -1358,6 +1362,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
13581362 } ,
13591363 ref discr,
13601364 ref variants,
1365+ discr_index,
13611366 } => {
13621367 if fallback {
13631368 let variant = self . layout . for_variant ( cx, dataful_variant) ;
@@ -1403,8 +1408,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
14031408 }
14041409 compute_field_path ( cx, & mut name,
14051410 self . layout ,
1406- self . layout . fields . offset ( 0 ) ,
1407- self . layout . field ( cx, 0 ) . size ) ;
1411+ self . layout . fields . offset ( discr_index ) ,
1412+ self . layout . field ( cx, discr_index ) . size ) ;
14081413 name. push_str ( & adt. variants [ * niche_variants. start ( ) ] . ident . as_str ( ) ) ;
14091414
14101415 // Create the (singleton) list of descriptions of union members.
@@ -1486,6 +1491,8 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
14861491 name : name. to_string ( ) ,
14871492 type_metadata : if use_enum_fallback ( cx) {
14881493 match self . discriminant_type_metadata {
1494+ // Discriminant is always the first field of our variant
1495+ // when using the enum fallback.
14891496 Some ( metadata) if i == 0 => metadata,
14901497 _ => type_metadata ( cx, ty, self . span )
14911498 }
@@ -1504,7 +1511,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
15041511
15051512#[ derive( Copy , Clone ) ]
15061513enum EnumDiscriminantInfo < ' ll > {
1507- RegularDiscriminant ( & ' ll DIType ) ,
1514+ RegularDiscriminant { discr_field : Field , discr_type_metadata : & ' ll DIType } ,
15081515 OptimizedDiscriminant ,
15091516 NoDiscriminant
15101517}
@@ -1535,15 +1542,26 @@ fn describe_enum_variant(
15351542 unique_type_id,
15361543 Some ( containing_scope) ) ;
15371544
1545+ let arg_name = |i : usize | {
1546+ if variant. ctor_kind == CtorKind :: Fn {
1547+ format ! ( "__{}" , i)
1548+ } else {
1549+ variant. fields [ i] . ident . to_string ( )
1550+ }
1551+ } ;
1552+
15381553 // Build an array of (field name, field type) pairs to be captured in the factory closure.
15391554 let ( offsets, args) = if use_enum_fallback ( cx) {
15401555 // If this is not a univariant enum, there is also the discriminant field.
15411556 let ( discr_offset, discr_arg) = match discriminant_info {
1542- RegularDiscriminant ( _ ) => {
1557+ RegularDiscriminant { discr_field , .. } => {
15431558 // We have the layout of an enum variant, we need the layout of the outer enum
15441559 let enum_layout = cx. layout_of ( layout. ty ) ;
1545- ( Some ( enum_layout. fields . offset ( 0 ) ) ,
1546- Some ( ( "RUST$ENUM$DISR" . to_owned ( ) , enum_layout. field ( cx, 0 ) . ty ) ) )
1560+ let offset = enum_layout. fields . offset ( discr_field. as_usize ( ) ) ;
1561+ let args = (
1562+ "RUST$ENUM$DISR" . to_owned ( ) ,
1563+ enum_layout. field ( cx, discr_field. as_usize ( ) ) . ty ) ;
1564+ ( Some ( offset) , Some ( args) )
15471565 }
15481566 _ => ( None , None ) ,
15491567 } ;
@@ -1552,12 +1570,7 @@ fn describe_enum_variant(
15521570 layout. fields . offset ( i)
15531571 } ) ) . collect ( ) ,
15541572 discr_arg. into_iter ( ) . chain ( ( 0 ..layout. fields . count ( ) ) . map ( |i| {
1555- let name = if variant. ctor_kind == CtorKind :: Fn {
1556- format ! ( "__{}" , i)
1557- } else {
1558- variant. fields [ i] . ident . to_string ( )
1559- } ;
1560- ( name, layout. field ( cx, i) . ty )
1573+ ( arg_name ( i) , layout. field ( cx, i) . ty )
15611574 } ) ) . collect ( )
15621575 )
15631576 } else {
@@ -1566,12 +1579,7 @@ fn describe_enum_variant(
15661579 layout. fields . offset ( i)
15671580 } ) . collect ( ) ,
15681581 ( 0 ..layout. fields . count ( ) ) . map ( |i| {
1569- let name = if variant. ctor_kind == CtorKind :: Fn {
1570- format ! ( "__{}" , i)
1571- } else {
1572- variant. fields [ i] . ident . to_string ( )
1573- } ;
1574- ( name, layout. field ( cx, i) . ty )
1582+ ( arg_name ( i) , layout. field ( cx, i) . ty )
15751583 } ) . collect ( )
15761584 )
15771585 } ;
@@ -1581,8 +1589,8 @@ fn describe_enum_variant(
15811589 offsets,
15821590 args,
15831591 discriminant_type_metadata : match discriminant_info {
1584- RegularDiscriminant ( discriminant_type_metadata ) => {
1585- Some ( discriminant_type_metadata )
1592+ RegularDiscriminant { discr_type_metadata , .. } => {
1593+ Some ( discr_type_metadata )
15861594 }
15871595 _ => None
15881596 } ,
@@ -1732,6 +1740,7 @@ fn prepare_enum_metadata(
17321740 layout:: Variants :: Multiple {
17331741 discr_kind : layout:: DiscriminantKind :: Niche { .. } ,
17341742 ref discr,
1743+ discr_index,
17351744 ..
17361745 } => {
17371746 // Find the integer type of the correct size.
@@ -1755,7 +1764,7 @@ fn prepare_enum_metadata(
17551764 UNKNOWN_LINE_NUMBER ,
17561765 size. bits ( ) ,
17571766 align. abi . bits ( ) as u32 ,
1758- layout. fields . offset ( 0 ) . bits ( ) ,
1767+ layout. fields . offset ( discr_index ) . bits ( ) ,
17591768 DIFlags :: FlagArtificial ,
17601769 discr_metadata) )
17611770 }
@@ -1764,6 +1773,7 @@ fn prepare_enum_metadata(
17641773 layout:: Variants :: Multiple {
17651774 discr_kind : layout:: DiscriminantKind :: Tag ,
17661775 ref discr,
1776+ discr_index,
17671777 ..
17681778 } => {
17691779 let discr_type = discr. value . to_ty ( cx. tcx ) ;
@@ -1779,7 +1789,7 @@ fn prepare_enum_metadata(
17791789 UNKNOWN_LINE_NUMBER ,
17801790 size. bits ( ) ,
17811791 align. bits ( ) as u32 ,
1782- layout. fields . offset ( 0 ) . bits ( ) ,
1792+ layout. fields . offset ( discr_index ) . bits ( ) ,
17831793 DIFlags :: FlagArtificial ,
17841794 discr_metadata) )
17851795 }
0 commit comments