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