use build::scope::LoopScope;
use hair::*;
use rustc::middle::region::CodeExtent;
-use rustc::middle::ty;
+use rustc::ty;
use rustc::mir::repr::*;
use syntax::codemap::Span;
// just use the name `this` uniformly
let this = self;
let expr_span = expr.span;
+ let scope_id = this.innermost_scope_id();
match expr.kind {
ExprKind::Scope { extent, value } => {
- this.in_scope(extent, block, |this| this.into(destination, block, value))
+ this.in_scope(extent, block, |this, _| this.into(destination, block, value))
}
ExprKind::Block { body: ast_block } => {
this.ast_block(destination, block, ast_block)
let mut then_block = this.cfg.start_new_block();
let mut else_block = this.cfg.start_new_block();
- this.cfg.terminate(block, Terminator::If {
+ this.cfg.terminate(block, scope_id, expr_span, TerminatorKind::If {
cond: operand,
targets: (then_block, else_block)
});
} else {
// Body of the `if` expression without an `else` clause must return `()`, thus
// we implicitly generate a `else {}` if it is not specified.
- this.cfg.push_assign_unit(else_block, expr_span, destination);
+ let scope_id = this.innermost_scope_id();
+ this.cfg.push_assign_unit(else_block, scope_id, expr_span, destination);
else_block
};
let join_block = this.cfg.start_new_block();
- this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
- this.cfg.terminate(else_block, Terminator::Goto { target: join_block });
+ this.cfg.terminate(then_block,
+ scope_id,
+ expr_span,
+ TerminatorKind::Goto { target: join_block });
+ this.cfg.terminate(else_block,
+ scope_id,
+ expr_span,
+ TerminatorKind::Goto { target: join_block });
join_block.unit()
}
LogicalOp::And => (else_block, false_block),
LogicalOp::Or => (true_block, else_block),
};
- this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });
+ this.cfg.terminate(block,
+ scope_id,
+ expr_span,
+ TerminatorKind::If { cond: lhs, targets: blocks });
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
- this.cfg.terminate(else_block, Terminator::If {
+ this.cfg.terminate(else_block, scope_id, expr_span, TerminatorKind::If {
cond: rhs,
targets: (true_block, false_block)
});
this.cfg.push_assign_constant(
- true_block, expr_span, destination,
+ true_block, scope_id, expr_span, destination,
Constant {
span: expr_span,
ty: this.hir.bool_ty(),
});
this.cfg.push_assign_constant(
- false_block, expr_span, destination,
+ false_block, scope_id, expr_span, destination,
Constant {
span: expr_span,
ty: this.hir.bool_ty(),
literal: this.hir.false_literal(),
});
- this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
- this.cfg.terminate(false_block, Terminator::Goto { target: join_block });
+ this.cfg.terminate(true_block,
+ scope_id,
+ expr_span,
+ TerminatorKind::Goto { target: join_block });
+ this.cfg.terminate(false_block,
+ scope_id,
+ expr_span,
+ TerminatorKind::Goto { target: join_block });
join_block.unit()
}
let exit_block = this.cfg.start_new_block();
// start the loop
- this.cfg.terminate(block, Terminator::Goto { target: loop_block });
+ this.cfg.terminate(block,
+ scope_id,
+ expr_span,
+ TerminatorKind::Goto { target: loop_block });
let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
// conduct the test, if necessary
let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
body_block = this.cfg.start_new_block();
this.cfg.terminate(loop_block_end,
- Terminator::If {
+ scope_id,
+ expr_span,
+ TerminatorKind::If {
cond: cond,
targets: (body_block, exit_block)
});
let tmp = this.get_unit_temp();
// Execute the body, branching back to the test.
let body_block_end = unpack!(this.into(&tmp, body_block, body));
- this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
+ this.cfg.terminate(body_block_end,
+ scope_id,
+ expr_span,
+ TerminatorKind::Goto { target: loop_block });
});
// If the loop may reach its exit_block, we assign an empty tuple to the
// destination to keep the MIR well-formed.
if might_break {
- this.cfg.push_assign_unit(exit_block, expr_span, destination);
+ this.cfg.push_assign_unit(exit_block, scope_id, expr_span, destination);
}
exit_block.unit()
}
// Note: we evaluate assignments right-to-left. This
// is better for borrowck interaction with overloaded
// operators like x[j] = x[i].
+ let lhs = this.hir.mirror(lhs);
+ let lhs_span = lhs.span;
let rhs = unpack!(block = this.as_operand(block, rhs));
let lhs = unpack!(block = this.as_lvalue(block, lhs));
- unpack!(block = this.build_drop(block, lhs.clone()));
- this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
+ unpack!(block = this.build_drop(block, lhs_span, lhs.clone()));
+ this.cfg.push_assign(block, scope_id, expr_span, &lhs, Rvalue::Use(rhs));
block.unit()
}
ExprKind::AssignOp { op, lhs, rhs } => {
// we don't have to drop prior contents or anything
// because AssignOp is only legal for Copy types
// (overloaded ops should be desugared into a call).
- this.cfg.push_assign(block, expr_span, &lhs,
+ this.cfg.push_assign(block, scope_id, expr_span, &lhs,
Rvalue::BinaryOp(op,
Operand::Consume(lhs.clone()),
rhs));
block = match value {
Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
None => {
- this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
+ this.cfg.push_assign_unit(block, scope_id,
+ expr_span, &Lvalue::ReturnPointer);
block
}
};
- let extent = this.extent_of_outermost_scope();
+ let extent = this.extent_of_return_scope();
this.exit_scope(expr_span, extent, block, END_BLOCK);
this.cfg.start_new_block().unit()
}
ExprKind::Call { ty, fun, args } => {
let diverges = match ty.sty {
- ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
+ ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
+ f.sig.0.output.diverges()
+ }
_ => false
};
let fun = unpack!(block = this.as_operand(block, fun));
let success = this.cfg.start_new_block();
let cleanup = this.diverge_cleanup();
- this.cfg.terminate(block, Terminator::Call {
+ this.cfg.terminate(block, scope_id, expr_span, TerminatorKind::Call {
func: fun,
args: args,
cleanup: cleanup,
});
let rvalue = unpack!(block = this.as_rvalue(block, expr));
- this.cfg.push_assign(block, expr_span, destination, rvalue);
+ this.cfg.push_assign(block, scope_id, expr_span, destination, rvalue);
block.unit()
}
}