@@ -25,7 +25,7 @@ use std::fmt;
25
25
use std:: i64;
26
26
use std:: iter;
27
27
use std:: mem;
28
- use std:: ops:: { Deref , Add , Sub , Mul , AddAssign } ;
28
+ use std:: ops:: { Deref , Add , Sub , Mul , AddAssign , RangeInclusive } ;
29
29
30
30
use ich:: StableHashingContext ;
31
31
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher ,
@@ -841,9 +841,9 @@ impl<'a, 'tcx> Struct {
841
841
( & Scalar ( Pointer ) , _) if !layout. ty . is_unsafe_ptr ( ) => {
842
842
Ok ( Some ( ( Size :: from_bytes ( 0 ) , Pointer ) ) )
843
843
}
844
- ( & CEnum { discr, .. } , & ty:: TyAdt ( def, _) ) => {
844
+ ( & General { discr, .. } , & ty:: TyAdt ( def, _) ) => {
845
845
if def. discriminants ( tcx) . all ( |d| d. to_u128_unchecked ( ) != 0 ) {
846
- Ok ( Some ( ( Size :: from_bytes ( 0 ) , discr) ) )
846
+ Ok ( Some ( ( layout . fields . offset ( 0 ) , discr) ) )
847
847
} else {
848
848
Ok ( None )
849
849
}
@@ -1095,18 +1095,6 @@ pub enum Layout {
1095
1095
1096
1096
// Remaining variants are all ADTs such as structs, enums or tuples.
1097
1097
1098
- /// C-like enums; basically an integer.
1099
- CEnum {
1100
- discr : Primitive ,
1101
- /// Inclusive discriminant range.
1102
- /// If min > max, it represents min...u64::MAX followed by 0...max.
1103
- // FIXME(eddyb) always use the shortest range, e.g. by finding
1104
- // the largest space between two consecutive discriminants and
1105
- // taking everything else as the (shortest) discriminant range.
1106
- min : u64 ,
1107
- max : u64
1108
- } ,
1109
-
1110
1098
/// Single-case enums, and structs/tuples.
1111
1099
Univariant ( Struct ) ,
1112
1100
@@ -1118,6 +1106,12 @@ pub enum Layout {
1118
1106
/// at a non-0 offset, after where the discriminant would go.
1119
1107
General {
1120
1108
discr : Primitive ,
1109
+ /// Inclusive wrap-around range of discriminant values, that is,
1110
+ /// if min > max, it represents min..=u64::MAX followed by 0..=max.
1111
+ // FIXME(eddyb) always use the shortest range, e.g. by finding
1112
+ // the largest space between two consecutive discriminants and
1113
+ // taking everything else as the (shortest) discriminant range.
1114
+ discr_range : RangeInclusive < u64 > ,
1121
1115
variants : Vec < Struct > ,
1122
1116
size : Size ,
1123
1117
align : Align ,
@@ -1240,7 +1234,6 @@ impl<'a, 'tcx> Layout {
1240
1234
FieldPlacement :: union ( def. struct_variant ( ) . fields . len ( ) )
1241
1235
}
1242
1236
1243
- CEnum { .. } |
1244
1237
General { .. } => FieldPlacement :: union ( 1 ) ,
1245
1238
1246
1239
NullablePointer { ref discr_offset, .. } => {
@@ -1250,19 +1243,17 @@ impl<'a, 'tcx> Layout {
1250
1243
}
1251
1244
} ;
1252
1245
let abi = match * layout {
1253
- Scalar ( value) |
1254
- CEnum { discr : value, .. } => Abi :: Scalar ( value) ,
1255
-
1246
+ Scalar ( value) => Abi :: Scalar ( value) ,
1256
1247
Vector { .. } => Abi :: Vector ,
1257
1248
1258
1249
Array { .. } |
1259
1250
FatPointer { .. } |
1260
1251
Univariant ( _) |
1261
- UntaggedUnion ( _) |
1262
- General { .. } => Abi :: Aggregate ,
1252
+ UntaggedUnion ( _) => Abi :: Aggregate ,
1263
1253
1264
- NullablePointer { discr, discr_offset, .. } => {
1265
- if discr_offset. bytes ( ) == 0 && discr. size ( cx) == layout. size ( cx) {
1254
+ General { discr, .. } |
1255
+ NullablePointer { discr, .. } => {
1256
+ if fields. offset ( 0 ) . bytes ( ) == 0 && discr. size ( cx) == layout. size ( cx) {
1266
1257
Abi :: Scalar ( discr)
1267
1258
} else {
1268
1259
Abi :: Aggregate
@@ -1431,82 +1422,54 @@ impl<'a, 'tcx> Layout {
1431
1422
1432
1423
// ADTs.
1433
1424
ty:: TyAdt ( def, substs) => {
1434
- if def. variants . is_empty ( ) {
1425
+ // Cache the field layouts.
1426
+ let variants = def. variants . iter ( ) . map ( |v| {
1427
+ v. fields . iter ( ) . map ( |field| {
1428
+ cx. layout_of ( field. ty ( tcx, substs) )
1429
+ } ) . collect :: < Result < Vec < _ > , _ > > ( )
1430
+ } ) . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1431
+
1432
+ if variants. is_empty ( ) {
1435
1433
// Uninhabitable; represent as unit
1436
1434
// (Typechecking will reject discriminant-sizing attrs.)
1437
1435
1438
1436
return success ( Univariant ( Struct :: new ( dl, & [ ] ,
1439
1437
& def. repr , StructKind :: AlwaysSizedUnivariant , ty) ?) ) ;
1440
1438
}
1441
1439
1442
- if def. is_enum ( ) && def. variants . iter ( ) . all ( |v| v. fields . is_empty ( ) ) {
1443
- // All bodies empty -> intlike
1444
- let ( mut min, mut max) = ( i64:: max_value ( ) , i64:: min_value ( ) ) ;
1445
- for discr in def. discriminants ( tcx) {
1446
- let x = discr. to_u128_unchecked ( ) as i64 ;
1447
- if x < min { min = x; }
1448
- if x > max { max = x; }
1449
- }
1450
-
1451
- // FIXME: should handle i128? signed-value based impl is weird and hard to
1452
- // grok.
1453
- let ( discr, signed) = Integer :: repr_discr ( tcx, ty, & def. repr , min, max) ;
1454
- return success ( CEnum {
1455
- discr : Int ( discr, signed) ,
1456
- // FIXME: should be u128?
1457
- min : min as u64 ,
1458
- max : max as u64
1459
- } ) ;
1460
- }
1461
-
1462
- if !def. is_enum ( ) || ( def. variants . len ( ) == 1 &&
1463
- !def. repr . inhibit_enum_layout_opt ( ) ) {
1440
+ if !def. is_enum ( ) || ( variants. len ( ) == 1 &&
1441
+ !def. repr . inhibit_enum_layout_opt ( ) &&
1442
+ !variants[ 0 ] . is_empty ( ) ) {
1464
1443
// Struct, or union, or univariant enum equivalent to a struct.
1465
1444
// (Typechecking will reject discriminant-sizing attrs.)
1466
1445
1467
- let kind = if def. is_enum ( ) || def . variants [ 0 ] . fields . len ( ) == 0 {
1446
+ let kind = if def. is_enum ( ) || variants[ 0 ] . len ( ) == 0 {
1468
1447
StructKind :: AlwaysSizedUnivariant
1469
1448
} else {
1470
1449
let param_env = tcx. param_env ( def. did ) ;
1471
- let fields = & def. variants [ 0 ] . fields ;
1472
- let last_field = & fields[ fields. len ( ) -1 ] ;
1450
+ let last_field = def. variants [ 0 ] . fields . last ( ) . unwrap ( ) ;
1473
1451
let always_sized = tcx. type_of ( last_field. did )
1474
1452
. is_sized ( tcx, param_env, DUMMY_SP ) ;
1475
1453
if !always_sized { StructKind :: MaybeUnsizedUnivariant }
1476
1454
else { StructKind :: AlwaysSizedUnivariant }
1477
1455
} ;
1478
1456
1479
- let fields = def. variants [ 0 ] . fields . iter ( ) . map ( |field| {
1480
- cx. layout_of ( field. ty ( tcx, substs) )
1481
- } ) . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1482
1457
let layout = if def. is_union ( ) {
1483
1458
let mut un = Union :: new ( dl, & def. repr ) ;
1484
- un. extend ( dl, fields . iter ( ) . map ( |& f| Ok ( f. layout ) ) , ty) ?;
1459
+ un. extend ( dl, variants [ 0 ] . iter ( ) . map ( |& f| Ok ( f. layout ) ) , ty) ?;
1485
1460
UntaggedUnion ( un)
1486
1461
} else {
1487
- Univariant ( Struct :: new ( dl, & fields , & def. repr , kind, ty) ?)
1462
+ Univariant ( Struct :: new ( dl, & variants [ 0 ] , & def. repr , kind, ty) ?)
1488
1463
} ;
1489
1464
return success ( layout) ;
1490
1465
}
1491
1466
1492
- // Since there's at least one
1493
- // non-empty body, explicit discriminants should have
1494
- // been rejected by a checker before this point.
1495
- for ( i, v) in def. variants . iter ( ) . enumerate ( ) {
1496
- if v. discr != ty:: VariantDiscr :: Relative ( i) {
1497
- bug ! ( "non-C-like enum {} with specified discriminants" ,
1498
- tcx. item_path_str( def. did) ) ;
1499
- }
1500
- }
1467
+ let no_explicit_discriminants = def. variants . iter ( ) . enumerate ( )
1468
+ . all ( |( i, v) | v. discr == ty:: VariantDiscr :: Relative ( i) ) ;
1501
1469
1502
- // Cache the substituted and normalized variant field types.
1503
- let variants = def. variants . iter ( ) . map ( |v| {
1504
- v. fields . iter ( ) . map ( |field| {
1505
- cx. layout_of ( field. ty ( tcx, substs) )
1506
- } ) . collect :: < Result < Vec < _ > , _ > > ( )
1507
- } ) . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1508
-
1509
- if variants. len ( ) == 2 && !def. repr . inhibit_enum_layout_opt ( ) {
1470
+ if variants. len ( ) == 2 &&
1471
+ !def. repr . inhibit_enum_layout_opt ( ) &&
1472
+ no_explicit_discriminants {
1510
1473
// Nullable pointer optimization
1511
1474
let st0 = Struct :: new ( dl, & variants[ 0 ] ,
1512
1475
& def. repr , StructKind :: AlwaysSizedUnivariant , ty) ?;
@@ -1554,16 +1517,23 @@ impl<'a, 'tcx> Layout {
1554
1517
}
1555
1518
}
1556
1519
1557
- // The general case.
1558
- let discr_max = ( variants. len ( ) - 1 ) as i64 ;
1559
- assert ! ( discr_max >= 0 ) ;
1560
- let ( min_ity, _) = Integer :: repr_discr ( tcx, ty, & def. repr , 0 , discr_max) ;
1520
+ let ( mut min, mut max) = ( i64:: max_value ( ) , i64:: min_value ( ) ) ;
1521
+ for discr in def. discriminants ( tcx) {
1522
+ let x = discr. to_u128_unchecked ( ) as i64 ;
1523
+ if x < min { min = x; }
1524
+ if x > max { max = x; }
1525
+ }
1526
+ // FIXME: should handle i128? signed-value based impl is weird and hard to
1527
+ // grok.
1528
+ let ( min_ity, signed) = Integer :: repr_discr ( tcx, ty, & def. repr , min, max) ;
1529
+
1561
1530
let mut align = dl. aggregate_align ;
1562
1531
let mut primitive_align = dl. aggregate_align ;
1563
1532
let mut size = Size :: from_bytes ( 0 ) ;
1564
1533
1565
1534
// We're interested in the smallest alignment, so start large.
1566
1535
let mut start_align = Align :: from_bytes ( 256 , 256 ) . unwrap ( ) ;
1536
+ assert_eq ! ( Integer :: for_abi_align( dl, start_align) , None ) ;
1567
1537
1568
1538
// Create the set of structs that represent each variant.
1569
1539
let mut variants = variants. into_iter ( ) . map ( |fields| {
@@ -1644,7 +1614,10 @@ impl<'a, 'tcx> Layout {
1644
1614
}
1645
1615
1646
1616
General {
1647
- discr : Int ( ity, false ) ,
1617
+ discr : Int ( ity, signed) ,
1618
+
1619
+ // FIXME: should be u128?
1620
+ discr_range : ( min as u64 ) ..=( max as u64 ) ,
1648
1621
variants,
1649
1622
size,
1650
1623
align,
@@ -1680,7 +1653,7 @@ impl<'a, 'tcx> Layout {
1680
1653
pub fn is_unsized ( & self ) -> bool {
1681
1654
match * self {
1682
1655
Scalar ( _) | Vector { ..} | FatPointer { ..} |
1683
- CEnum { .. } | UntaggedUnion { ..} | General { ..} |
1656
+ UntaggedUnion { ..} | General { ..} |
1684
1657
NullablePointer { ..} => false ,
1685
1658
1686
1659
Array { sized, .. } |
@@ -1720,7 +1693,6 @@ impl<'a, 'tcx> Layout {
1720
1693
metadata. size ( dl) ) . abi_align ( self . align ( dl) )
1721
1694
}
1722
1695
1723
- CEnum { discr, .. } => discr. size ( dl) ,
1724
1696
General { size, .. } => size,
1725
1697
UntaggedUnion ( ref un) => un. stride ( ) ,
1726
1698
@@ -1754,7 +1726,6 @@ impl<'a, 'tcx> Layout {
1754
1726
Pointer . align ( dl) . max ( metadata. align ( dl) )
1755
1727
}
1756
1728
1757
- CEnum { discr, .. } => discr. align ( dl) ,
1758
1729
Array { align, .. } | General { align, .. } => align,
1759
1730
UntaggedUnion ( ref un) => un. align ,
1760
1731
@@ -1856,16 +1827,6 @@ impl<'a, 'tcx> Layout {
1856
1827
}
1857
1828
} ;
1858
1829
1859
- let build_primitive_info = |name : ast:: Name , value : Primitive | {
1860
- session:: VariantInfo {
1861
- name : Some ( name. to_string ( ) ) ,
1862
- kind : session:: SizeKind :: Exact ,
1863
- align : value. align ( tcx) . abi ( ) ,
1864
- size : value. size ( tcx) . bytes ( ) ,
1865
- fields : vec ! [ ] ,
1866
- }
1867
- } ;
1868
-
1869
1830
let build_variant_info = |n : Option < ast:: Name > ,
1870
1831
flds : & [ ( ast:: Name , Ty < ' tcx > ) ] ,
1871
1832
s : & Struct | {
@@ -1959,17 +1920,6 @@ impl<'a, 'tcx> Layout {
1959
1920
record ( adt_kind. into ( ) , None , Vec :: new ( ) ) ;
1960
1921
}
1961
1922
1962
- Layout :: CEnum { discr, .. } => {
1963
- debug ! ( "print-type-size t: `{:?}` adt c-like enum" , ty) ;
1964
- let variant_infos: Vec < _ > =
1965
- adt_def. variants . iter ( )
1966
- . map ( |variant_def| {
1967
- build_primitive_info ( variant_def. name , discr)
1968
- } )
1969
- . collect ( ) ;
1970
- record ( adt_kind. into ( ) , Some ( discr. size ( tcx) ) , variant_infos) ;
1971
- }
1972
-
1973
1923
// other cases provide little interesting (i.e. adjustable
1974
1924
// via representation tweaks) size info beyond total size.
1975
1925
Layout :: Scalar ( _) |
@@ -2284,6 +2234,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
2284
2234
FullLayout {
2285
2235
variant_index : Some ( variant_index) ,
2286
2236
fields,
2237
+ abi : Abi :: Aggregate ,
2287
2238
..* self
2288
2239
}
2289
2240
}
@@ -2356,7 +2307,6 @@ impl<'a, 'tcx> FullLayout<'tcx> {
2356
2307
match self . variant_index {
2357
2308
None => match * self . layout {
2358
2309
// Discriminant field for enums (where applicable).
2359
- CEnum { discr, .. } |
2360
2310
General { discr, .. } |
2361
2311
NullablePointer { discr, .. } => {
2362
2312
return [ discr. to_ty ( tcx) ] [ i] ;
@@ -2416,19 +2366,23 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
2416
2366
FatPointer ( ref metadata) => {
2417
2367
metadata. hash_stable ( hcx, hasher) ;
2418
2368
}
2419
- CEnum { discr, min, max } => {
2420
- discr. hash_stable ( hcx, hasher) ;
2421
- min. hash_stable ( hcx, hasher) ;
2422
- max. hash_stable ( hcx, hasher) ;
2423
- }
2424
2369
Univariant ( ref variant) => {
2425
2370
variant. hash_stable ( hcx, hasher) ;
2426
2371
}
2427
2372
UntaggedUnion ( ref un) => {
2428
2373
un. hash_stable ( hcx, hasher) ;
2429
2374
}
2430
- General { discr, ref variants, size, align, primitive_align } => {
2375
+ General {
2376
+ discr,
2377
+ discr_range : RangeInclusive { start, end } ,
2378
+ ref variants,
2379
+ size,
2380
+ align,
2381
+ primitive_align
2382
+ } => {
2431
2383
discr. hash_stable ( hcx, hasher) ;
2384
+ start. hash_stable ( hcx, hasher) ;
2385
+ end. hash_stable ( hcx, hasher) ;
2432
2386
variants. hash_stable ( hcx, hasher) ;
2433
2387
size. hash_stable ( hcx, hasher) ;
2434
2388
align. hash_stable ( hcx, hasher) ;
0 commit comments