@@ -19,6 +19,7 @@ use hir::def::CtorKind;
19
19
use hir:: def_id:: DefId ;
20
20
use ty:: subst:: Substs ;
21
21
use ty:: { self , AdtDef , ClosureSubsts , Region , Ty } ;
22
+ use ty:: fold:: { TypeFoldable , TypeFolder , TypeVisitor } ;
22
23
use util:: ppaux;
23
24
use rustc_back:: slice;
24
25
use hir:: InlineAsm ;
@@ -63,8 +64,7 @@ macro_rules! newtype_index {
63
64
}
64
65
65
66
/// Lowered representation of a single function.
66
- // Do not implement clone for Mir, which can be accidently done and kind of expensive.
67
- #[ derive( RustcEncodable , RustcDecodable , Debug ) ]
67
+ #[ derive( Clone , RustcEncodable , RustcDecodable , Debug ) ]
68
68
pub struct Mir < ' tcx > {
69
69
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
70
70
/// that indexes into this vector.
@@ -1333,3 +1333,347 @@ impl Location {
1333
1333
}
1334
1334
}
1335
1335
}
1336
+
1337
+
1338
+ /*
1339
+ * TypeFoldable implementations for MIR types
1340
+ */
1341
+
1342
+ impl < ' tcx > TypeFoldable < ' tcx > for Mir < ' tcx > {
1343
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1344
+ Mir {
1345
+ basic_blocks : self . basic_blocks . fold_with ( folder) ,
1346
+ visibility_scopes : self . visibility_scopes . clone ( ) ,
1347
+ promoted : self . promoted . fold_with ( folder) ,
1348
+ return_ty : self . return_ty . fold_with ( folder) ,
1349
+ local_decls : self . local_decls . fold_with ( folder) ,
1350
+ arg_count : self . arg_count ,
1351
+ upvar_decls : self . upvar_decls . clone ( ) ,
1352
+ spread_arg : self . spread_arg ,
1353
+ span : self . span ,
1354
+ cache : cache:: Cache :: new ( )
1355
+ }
1356
+ }
1357
+
1358
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1359
+ self . basic_blocks . visit_with ( visitor) ||
1360
+ self . promoted . visit_with ( visitor) ||
1361
+ self . return_ty . visit_with ( visitor) ||
1362
+ self . local_decls . visit_with ( visitor)
1363
+ }
1364
+ }
1365
+
1366
+ impl < ' tcx > TypeFoldable < ' tcx > for LocalDecl < ' tcx > {
1367
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1368
+ LocalDecl {
1369
+ ty : self . ty . fold_with ( folder) ,
1370
+ ..self . clone ( )
1371
+ }
1372
+ }
1373
+
1374
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1375
+ self . ty . visit_with ( visitor)
1376
+ }
1377
+ }
1378
+
1379
+ impl < ' tcx > TypeFoldable < ' tcx > for BasicBlockData < ' tcx > {
1380
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1381
+ BasicBlockData {
1382
+ statements : self . statements . fold_with ( folder) ,
1383
+ terminator : self . terminator . fold_with ( folder) ,
1384
+ is_cleanup : self . is_cleanup
1385
+ }
1386
+ }
1387
+
1388
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1389
+ self . statements . visit_with ( visitor) || self . terminator . visit_with ( visitor)
1390
+ }
1391
+ }
1392
+
1393
+ impl < ' tcx > TypeFoldable < ' tcx > for Statement < ' tcx > {
1394
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1395
+ use mir:: StatementKind :: * ;
1396
+
1397
+ let kind = match self . kind {
1398
+ Assign ( ref lval, ref rval) => Assign ( lval. fold_with ( folder) , rval. fold_with ( folder) ) ,
1399
+ SetDiscriminant { ref lvalue, variant_index } => SetDiscriminant {
1400
+ lvalue : lvalue. fold_with ( folder) ,
1401
+ variant_index : variant_index
1402
+ } ,
1403
+ StorageLive ( ref lval) => StorageLive ( lval. fold_with ( folder) ) ,
1404
+ StorageDead ( ref lval) => StorageDead ( lval. fold_with ( folder) ) ,
1405
+ InlineAsm { ref asm, ref outputs, ref inputs } => InlineAsm {
1406
+ asm : asm. clone ( ) ,
1407
+ outputs : outputs. fold_with ( folder) ,
1408
+ inputs : inputs. fold_with ( folder)
1409
+ } ,
1410
+ Nop => Nop ,
1411
+ } ;
1412
+ Statement {
1413
+ source_info : self . source_info ,
1414
+ kind : kind
1415
+ }
1416
+ }
1417
+
1418
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1419
+ use mir:: StatementKind :: * ;
1420
+
1421
+ match self . kind {
1422
+ Assign ( ref lval, ref rval) => { lval. visit_with ( visitor) || rval. visit_with ( visitor) }
1423
+ SetDiscriminant { ref lvalue, .. } |
1424
+ StorageLive ( ref lvalue) |
1425
+ StorageDead ( ref lvalue) => lvalue. visit_with ( visitor) ,
1426
+ InlineAsm { ref outputs, ref inputs, .. } =>
1427
+ outputs. visit_with ( visitor) || inputs. visit_with ( visitor) ,
1428
+ Nop => false ,
1429
+ }
1430
+ }
1431
+ }
1432
+
1433
+ impl < ' tcx > TypeFoldable < ' tcx > for Terminator < ' tcx > {
1434
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1435
+ use mir:: TerminatorKind :: * ;
1436
+
1437
+ let kind = match self . kind {
1438
+ Goto { target } => Goto { target : target } ,
1439
+ SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
1440
+ discr : discr. fold_with ( folder) ,
1441
+ switch_ty : switch_ty. fold_with ( folder) ,
1442
+ values : values. clone ( ) ,
1443
+ targets : targets. clone ( )
1444
+ } ,
1445
+ Drop { ref location, target, unwind } => Drop {
1446
+ location : location. fold_with ( folder) ,
1447
+ target : target,
1448
+ unwind : unwind
1449
+ } ,
1450
+ DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
1451
+ location : location. fold_with ( folder) ,
1452
+ value : value. fold_with ( folder) ,
1453
+ target : target,
1454
+ unwind : unwind
1455
+ } ,
1456
+ Call { ref func, ref args, ref destination, cleanup } => {
1457
+ let dest = destination. as_ref ( ) . map ( |& ( ref loc, dest) | {
1458
+ ( loc. fold_with ( folder) , dest)
1459
+ } ) ;
1460
+
1461
+ Call {
1462
+ func : func. fold_with ( folder) ,
1463
+ args : args. fold_with ( folder) ,
1464
+ destination : dest,
1465
+ cleanup : cleanup
1466
+ }
1467
+ } ,
1468
+ Assert { ref cond, expected, ref msg, target, cleanup } => {
1469
+ let msg = if let AssertMessage :: BoundsCheck { ref len, ref index } = * msg {
1470
+ AssertMessage :: BoundsCheck {
1471
+ len : len. fold_with ( folder) ,
1472
+ index : index. fold_with ( folder) ,
1473
+ }
1474
+ } else {
1475
+ msg. clone ( )
1476
+ } ;
1477
+ Assert {
1478
+ cond : cond. fold_with ( folder) ,
1479
+ expected : expected,
1480
+ msg : msg,
1481
+ target : target,
1482
+ cleanup : cleanup
1483
+ }
1484
+ } ,
1485
+ Resume => Resume ,
1486
+ Return => Return ,
1487
+ Unreachable => Unreachable ,
1488
+ } ;
1489
+ Terminator {
1490
+ source_info : self . source_info ,
1491
+ kind : kind
1492
+ }
1493
+ }
1494
+
1495
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1496
+ use mir:: TerminatorKind :: * ;
1497
+
1498
+ match self . kind {
1499
+ SwitchInt { ref discr, switch_ty, .. } =>
1500
+ discr. visit_with ( visitor) || switch_ty. visit_with ( visitor) ,
1501
+ Drop { ref location, ..} => location. visit_with ( visitor) ,
1502
+ DropAndReplace { ref location, ref value, ..} =>
1503
+ location. visit_with ( visitor) || value. visit_with ( visitor) ,
1504
+ Call { ref func, ref args, ref destination, .. } => {
1505
+ let dest = if let Some ( ( ref loc, _) ) = * destination {
1506
+ loc. visit_with ( visitor)
1507
+ } else { false } ;
1508
+ dest || func. visit_with ( visitor) || args. visit_with ( visitor)
1509
+ } ,
1510
+ Assert { ref cond, ref msg, .. } => {
1511
+ if cond. visit_with ( visitor) {
1512
+ if let AssertMessage :: BoundsCheck { ref len, ref index } = * msg {
1513
+ len. visit_with ( visitor) || index. visit_with ( visitor)
1514
+ } else {
1515
+ false
1516
+ }
1517
+ } else {
1518
+ false
1519
+ }
1520
+ } ,
1521
+ Goto { .. } |
1522
+ Resume |
1523
+ Return |
1524
+ Unreachable => false
1525
+ }
1526
+ }
1527
+ }
1528
+
1529
+ impl < ' tcx > TypeFoldable < ' tcx > for Lvalue < ' tcx > {
1530
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1531
+ match self {
1532
+ & Lvalue :: Projection ( ref p) => Lvalue :: Projection ( p. fold_with ( folder) ) ,
1533
+ _ => self . clone ( )
1534
+ }
1535
+ }
1536
+
1537
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1538
+ if let & Lvalue :: Projection ( ref p) = self {
1539
+ p. visit_with ( visitor)
1540
+ } else {
1541
+ false
1542
+ }
1543
+ }
1544
+ }
1545
+
1546
+ impl < ' tcx > TypeFoldable < ' tcx > for Rvalue < ' tcx > {
1547
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1548
+ use mir:: Rvalue :: * ;
1549
+ match * self {
1550
+ Use ( ref op) => Use ( op. fold_with ( folder) ) ,
1551
+ Repeat ( ref op, len) => Repeat ( op. fold_with ( folder) , len) ,
1552
+ Ref ( region, bk, ref lval) => Ref ( region. fold_with ( folder) , bk, lval. fold_with ( folder) ) ,
1553
+ Len ( ref lval) => Len ( lval. fold_with ( folder) ) ,
1554
+ Cast ( kind, ref op, ty) => Cast ( kind, op. fold_with ( folder) , ty. fold_with ( folder) ) ,
1555
+ BinaryOp ( op, ref rhs, ref lhs) =>
1556
+ BinaryOp ( op, rhs. fold_with ( folder) , lhs. fold_with ( folder) ) ,
1557
+ CheckedBinaryOp ( op, ref rhs, ref lhs) =>
1558
+ CheckedBinaryOp ( op, rhs. fold_with ( folder) , lhs. fold_with ( folder) ) ,
1559
+ UnaryOp ( op, ref val) => UnaryOp ( op, val. fold_with ( folder) ) ,
1560
+ Discriminant ( ref lval) => Discriminant ( lval. fold_with ( folder) ) ,
1561
+ Box ( ty) => Box ( ty. fold_with ( folder) ) ,
1562
+ Aggregate ( ref kind, ref fields) => {
1563
+ let kind = match * kind {
1564
+ AggregateKind :: Array ( ty) => AggregateKind :: Array ( ty. fold_with ( folder) ) ,
1565
+ AggregateKind :: Tuple => AggregateKind :: Tuple ,
1566
+ AggregateKind :: Adt ( def, v, substs, n) =>
1567
+ AggregateKind :: Adt ( def, v, substs. fold_with ( folder) , n) ,
1568
+ AggregateKind :: Closure ( id, substs) =>
1569
+ AggregateKind :: Closure ( id, substs. fold_with ( folder) )
1570
+ } ;
1571
+ Aggregate ( kind, fields. fold_with ( folder) )
1572
+ }
1573
+ }
1574
+ }
1575
+
1576
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1577
+ use mir:: Rvalue :: * ;
1578
+ match * self {
1579
+ Use ( ref op) => op. visit_with ( visitor) ,
1580
+ Repeat ( ref op, _) => op. visit_with ( visitor) ,
1581
+ Ref ( region, _, ref lval) => region. visit_with ( visitor) || lval. visit_with ( visitor) ,
1582
+ Len ( ref lval) => lval. visit_with ( visitor) ,
1583
+ Cast ( _, ref op, ty) => op. visit_with ( visitor) || ty. visit_with ( visitor) ,
1584
+ BinaryOp ( _, ref rhs, ref lhs) |
1585
+ CheckedBinaryOp ( _, ref rhs, ref lhs) =>
1586
+ rhs. visit_with ( visitor) || lhs. visit_with ( visitor) ,
1587
+ UnaryOp ( _, ref val) => val. visit_with ( visitor) ,
1588
+ Discriminant ( ref lval) => lval. visit_with ( visitor) ,
1589
+ Box ( ty) => ty. visit_with ( visitor) ,
1590
+ Aggregate ( ref kind, ref fields) => {
1591
+ ( match * kind {
1592
+ AggregateKind :: Array ( ty) => ty. visit_with ( visitor) ,
1593
+ AggregateKind :: Tuple => false ,
1594
+ AggregateKind :: Adt ( _, _, substs, _) => substs. visit_with ( visitor) ,
1595
+ AggregateKind :: Closure ( _, substs) => substs. visit_with ( visitor)
1596
+ } ) || fields. visit_with ( visitor)
1597
+ }
1598
+ }
1599
+ }
1600
+ }
1601
+
1602
+ impl < ' tcx > TypeFoldable < ' tcx > for Operand < ' tcx > {
1603
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1604
+ match * self {
1605
+ Operand :: Consume ( ref lval) => Operand :: Consume ( lval. fold_with ( folder) ) ,
1606
+ Operand :: Constant ( ref c) => Operand :: Constant ( c. fold_with ( folder) ) ,
1607
+ }
1608
+ }
1609
+
1610
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1611
+ match * self {
1612
+ Operand :: Consume ( ref lval) => lval. visit_with ( visitor) ,
1613
+ Operand :: Constant ( ref c) => c. visit_with ( visitor)
1614
+ }
1615
+ }
1616
+ }
1617
+
1618
+ impl < ' tcx , B , V > TypeFoldable < ' tcx > for Projection < ' tcx , B , V >
1619
+ where B : TypeFoldable < ' tcx > , V : TypeFoldable < ' tcx >
1620
+ {
1621
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1622
+ use mir:: ProjectionElem :: * ;
1623
+
1624
+ let base = self . base . fold_with ( folder) ;
1625
+ let elem = match self . elem {
1626
+ Deref => Deref ,
1627
+ Field ( f, ty) => Field ( f, ty. fold_with ( folder) ) ,
1628
+ Index ( ref v) => Index ( v. fold_with ( folder) ) ,
1629
+ ref elem => elem. clone ( )
1630
+ } ;
1631
+
1632
+ Projection {
1633
+ base : base,
1634
+ elem : elem
1635
+ }
1636
+ }
1637
+
1638
+ fn super_visit_with < Vs : TypeVisitor < ' tcx > > ( & self , visitor : & mut Vs ) -> bool {
1639
+ use mir:: ProjectionElem :: * ;
1640
+
1641
+ self . base . visit_with ( visitor) ||
1642
+ match self . elem {
1643
+ Field ( _, ty) => ty. visit_with ( visitor) ,
1644
+ Index ( ref v) => v. visit_with ( visitor) ,
1645
+ _ => false
1646
+ }
1647
+ }
1648
+ }
1649
+
1650
+ impl < ' tcx > TypeFoldable < ' tcx > for Constant < ' tcx > {
1651
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1652
+ Constant {
1653
+ span : self . span . clone ( ) ,
1654
+ ty : self . ty . fold_with ( folder) ,
1655
+ literal : self . literal . fold_with ( folder)
1656
+ }
1657
+ }
1658
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1659
+ self . ty . visit_with ( visitor) || self . literal . visit_with ( visitor)
1660
+ }
1661
+ }
1662
+
1663
+ impl < ' tcx > TypeFoldable < ' tcx > for Literal < ' tcx > {
1664
+ fn super_fold_with < ' gcx : ' tcx , F : TypeFolder < ' gcx , ' tcx > > ( & self , folder : & mut F ) -> Self {
1665
+ match * self {
1666
+ Literal :: Item { def_id, substs } => Literal :: Item {
1667
+ def_id : def_id,
1668
+ substs : substs. fold_with ( folder)
1669
+ } ,
1670
+ _ => self . clone ( )
1671
+ }
1672
+ }
1673
+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1674
+ match * self {
1675
+ Literal :: Item { substs, .. } => substs. visit_with ( visitor) ,
1676
+ _ => false
1677
+ }
1678
+ }
1679
+ }
0 commit comments