@@ -22,6 +22,7 @@ use rustc::hir::CodegenFnAttrFlags;
22
22
use rustc:: hir:: def:: CtorKind ;
23
23
use rustc:: hir:: def_id:: { DefId , CrateNum , LOCAL_CRATE } ;
24
24
use rustc:: ich:: NodeIdHashingMode ;
25
+ use rustc:: mir:: Field ;
25
26
use rustc:: mir:: interpret:: truncate;
26
27
use rustc_data_structures:: fingerprint:: Fingerprint ;
27
28
use rustc:: ty:: Instance ;
@@ -1306,12 +1307,15 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
1306
1307
}
1307
1308
layout:: Variants :: Multiple {
1308
1309
discr_kind : layout:: DiscriminantKind :: Tag ,
1310
+ discr_index,
1309
1311
ref variants,
1310
1312
..
1311
1313
} => {
1312
1314
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
+ }
1315
1319
} else {
1316
1320
// This doesn't matter in this case.
1317
1321
NoDiscriminant
@@ -1358,6 +1362,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
1358
1362
} ,
1359
1363
ref discr,
1360
1364
ref variants,
1365
+ discr_index,
1361
1366
} => {
1362
1367
if fallback {
1363
1368
let variant = self . layout . for_variant ( cx, dataful_variant) ;
@@ -1403,8 +1408,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
1403
1408
}
1404
1409
compute_field_path ( cx, & mut name,
1405
1410
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 ) ;
1408
1413
name. push_str ( & adt. variants [ * niche_variants. start ( ) ] . ident . as_str ( ) ) ;
1409
1414
1410
1415
// Create the (singleton) list of descriptions of union members.
@@ -1486,6 +1491,8 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
1486
1491
name : name. to_string ( ) ,
1487
1492
type_metadata : if use_enum_fallback ( cx) {
1488
1493
match self . discriminant_type_metadata {
1494
+ // Discriminant is always the first field of our variant
1495
+ // when using the enum fallback.
1489
1496
Some ( metadata) if i == 0 => metadata,
1490
1497
_ => type_metadata ( cx, ty, self . span )
1491
1498
}
@@ -1504,7 +1511,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
1504
1511
1505
1512
#[ derive( Copy , Clone ) ]
1506
1513
enum EnumDiscriminantInfo < ' ll > {
1507
- RegularDiscriminant ( & ' ll DIType ) ,
1514
+ RegularDiscriminant { discr_field : Field , discr_type_metadata : & ' ll DIType } ,
1508
1515
OptimizedDiscriminant ,
1509
1516
NoDiscriminant
1510
1517
}
@@ -1535,15 +1542,26 @@ fn describe_enum_variant(
1535
1542
unique_type_id,
1536
1543
Some ( containing_scope) ) ;
1537
1544
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
+
1538
1553
// Build an array of (field name, field type) pairs to be captured in the factory closure.
1539
1554
let ( offsets, args) = if use_enum_fallback ( cx) {
1540
1555
// If this is not a univariant enum, there is also the discriminant field.
1541
1556
let ( discr_offset, discr_arg) = match discriminant_info {
1542
- RegularDiscriminant ( _ ) => {
1557
+ RegularDiscriminant { discr_field , .. } => {
1543
1558
// We have the layout of an enum variant, we need the layout of the outer enum
1544
1559
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) )
1547
1565
}
1548
1566
_ => ( None , None ) ,
1549
1567
} ;
@@ -1552,12 +1570,7 @@ fn describe_enum_variant(
1552
1570
layout. fields . offset ( i)
1553
1571
} ) ) . collect ( ) ,
1554
1572
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 )
1561
1574
} ) ) . collect ( )
1562
1575
)
1563
1576
} else {
@@ -1566,12 +1579,7 @@ fn describe_enum_variant(
1566
1579
layout. fields . offset ( i)
1567
1580
} ) . collect ( ) ,
1568
1581
( 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 )
1575
1583
} ) . collect ( )
1576
1584
)
1577
1585
} ;
@@ -1581,8 +1589,8 @@ fn describe_enum_variant(
1581
1589
offsets,
1582
1590
args,
1583
1591
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 )
1586
1594
}
1587
1595
_ => None
1588
1596
} ,
@@ -1732,6 +1740,7 @@ fn prepare_enum_metadata(
1732
1740
layout:: Variants :: Multiple {
1733
1741
discr_kind : layout:: DiscriminantKind :: Niche { .. } ,
1734
1742
ref discr,
1743
+ discr_index,
1735
1744
..
1736
1745
} => {
1737
1746
// Find the integer type of the correct size.
@@ -1755,7 +1764,7 @@ fn prepare_enum_metadata(
1755
1764
UNKNOWN_LINE_NUMBER ,
1756
1765
size. bits ( ) ,
1757
1766
align. abi . bits ( ) as u32 ,
1758
- layout. fields . offset ( 0 ) . bits ( ) ,
1767
+ layout. fields . offset ( discr_index ) . bits ( ) ,
1759
1768
DIFlags :: FlagArtificial ,
1760
1769
discr_metadata) )
1761
1770
}
@@ -1764,6 +1773,7 @@ fn prepare_enum_metadata(
1764
1773
layout:: Variants :: Multiple {
1765
1774
discr_kind : layout:: DiscriminantKind :: Tag ,
1766
1775
ref discr,
1776
+ discr_index,
1767
1777
..
1768
1778
} => {
1769
1779
let discr_type = discr. value . to_ty ( cx. tcx ) ;
@@ -1779,7 +1789,7 @@ fn prepare_enum_metadata(
1779
1789
UNKNOWN_LINE_NUMBER ,
1780
1790
size. bits ( ) ,
1781
1791
align. bits ( ) as u32 ,
1782
- layout. fields . offset ( 0 ) . bits ( ) ,
1792
+ layout. fields . offset ( discr_index ) . bits ( ) ,
1783
1793
DIFlags :: FlagArtificial ,
1784
1794
discr_metadata) )
1785
1795
}
0 commit comments