@@ -19,6 +19,7 @@ use hir::def::CtorKind;
1919use hir:: def_id:: DefId ;
2020use ty:: subst:: Substs ;
2121use ty:: { self , AdtDef , ClosureSubsts , Region , Ty } ;
22+ use ty:: fold:: { TypeFoldable , TypeFolder , TypeVisitor } ;
2223use util:: ppaux;
2324use rustc_back:: slice;
2425use hir:: InlineAsm ;
@@ -63,8 +64,7 @@ macro_rules! newtype_index {
6364}
6465
6566/// 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 ) ]
6868pub struct Mir < ' tcx > {
6969 /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
7070 /// that indexes into this vector.
@@ -1333,3 +1333,347 @@ impl Location {
13331333 }
13341334 }
13351335}
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