Skip to content

Commit 0345a28

Browse files
committed
Implement TypeFoldable on the MIR types
Inlining needs to apply the substitutions from the callsite. Also implements TypeFoldable on IndexVec
1 parent 53f9730 commit 0345a28

File tree

3 files changed

+409
-0
lines changed

3 files changed

+409
-0
lines changed

src/librustc/mir/repr.rs

Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_data_structures::control_flow_graph::ControlFlowGraph;
1818
use hir::def_id::DefId;
1919
use ty::subst::Substs;
2020
use ty::{self, AdtDef, ClosureSubsts, Region, Ty};
21+
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
2122
use util::ppaux;
2223
use rustc_back::slice;
2324
use hir::InlineAsm;
@@ -1324,3 +1325,389 @@ impl Location {
13241325
}
13251326
}
13261327
}
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

Comments
 (0)