@@ -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
}
@@ -1547,11 +1554,14 @@ fn describe_enum_variant(
1547
1554
let ( offsets, args) = if use_enum_fallback ( cx) {
1548
1555
// If this is not a univariant enum, there is also the discriminant field.
1549
1556
let ( discr_offset, discr_arg) = match discriminant_info {
1550
- RegularDiscriminant ( _ ) => {
1557
+ RegularDiscriminant { discr_field , .. } => {
1551
1558
// We have the layout of an enum variant, we need the layout of the outer enum
1552
1559
let enum_layout = cx. layout_of ( layout. ty ) ;
1553
- ( Some ( enum_layout. fields . offset ( 0 ) ) ,
1554
- 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) )
1555
1565
}
1556
1566
_ => ( None , None ) ,
1557
1567
} ;
@@ -1579,8 +1589,8 @@ fn describe_enum_variant(
1579
1589
offsets,
1580
1590
args,
1581
1591
discriminant_type_metadata : match discriminant_info {
1582
- RegularDiscriminant ( discriminant_type_metadata ) => {
1583
- Some ( discriminant_type_metadata )
1592
+ RegularDiscriminant { discr_type_metadata , .. } => {
1593
+ Some ( discr_type_metadata )
1584
1594
}
1585
1595
_ => None
1586
1596
} ,
@@ -1730,6 +1740,7 @@ fn prepare_enum_metadata(
1730
1740
layout:: Variants :: Multiple {
1731
1741
discr_kind : layout:: DiscriminantKind :: Niche { .. } ,
1732
1742
ref discr,
1743
+ discr_index,
1733
1744
..
1734
1745
} => {
1735
1746
// Find the integer type of the correct size.
@@ -1753,7 +1764,7 @@ fn prepare_enum_metadata(
1753
1764
UNKNOWN_LINE_NUMBER ,
1754
1765
size. bits ( ) ,
1755
1766
align. abi . bits ( ) as u32 ,
1756
- layout. fields . offset ( 0 ) . bits ( ) ,
1767
+ layout. fields . offset ( discr_index ) . bits ( ) ,
1757
1768
DIFlags :: FlagArtificial ,
1758
1769
discr_metadata) )
1759
1770
}
@@ -1762,6 +1773,7 @@ fn prepare_enum_metadata(
1762
1773
layout:: Variants :: Multiple {
1763
1774
discr_kind : layout:: DiscriminantKind :: Tag ,
1764
1775
ref discr,
1776
+ discr_index,
1765
1777
..
1766
1778
} => {
1767
1779
let discr_type = discr. value . to_ty ( cx. tcx ) ;
@@ -1777,7 +1789,7 @@ fn prepare_enum_metadata(
1777
1789
UNKNOWN_LINE_NUMBER ,
1778
1790
size. bits ( ) ,
1779
1791
align. bits ( ) as u32 ,
1780
- layout. fields . offset ( 0 ) . bits ( ) ,
1792
+ layout. fields . offset ( discr_index ) . bits ( ) ,
1781
1793
DIFlags :: FlagArtificial ,
1782
1794
discr_metadata) )
1783
1795
}
0 commit comments