})
}
- // Helper method for generating MIR inside a conditional block.
- pub fn with_cond<F>(&mut self, block: BasicBlock, span: Span,
- cond: Operand<'tcx>, f: F) -> BasicBlock
- where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>, BasicBlock) -> BasicBlock {
+ // Helper method for generating a conditional branch
+ // Returns (TrueBlock, FalseBlock)
+ pub fn build_cond_br(&mut self, block: BasicBlock, span: Span,
+ cond: Operand<'tcx>) -> (BasicBlock, BasicBlock) {
let scope_id = self.innermost_scope_id();
let then_block = self.cfg.start_new_block();
targets: (then_block, else_block)
});
- let after = f(self, then_block);
-
- // If the returned block isn't terminated, add a branch to the "else"
- // block
- if !self.cfg.terminated(after) {
- self.cfg.terminate(after, scope_id, span,
- TerminatorKind::Goto { target: else_block });
- }
-
- else_block
+ (then_block, else_block)
}
}
this.cfg.push_assign(block, scope_id, expr_span, &is_min,
Rvalue::BinaryOp(BinOp::Eq, arg.clone(), minval));
- block = this.with_cond(
- block, expr_span, Operand::Consume(is_min), |this, block| {
- this.panic(block, "attempted to negate with overflow", expr_span);
- block
- });
+ let (of_block, ok_block) = this.build_cond_br(block, expr_span,
+ Operand::Consume(is_min));
+ this.panic(of_block, "attempted to negate with overflow", expr_span);
+ block = ok_block;
}
block.and(Rvalue::UnaryOp(op, arg))
}
}
}
- pub fn build_binary_op(&mut self, mut block: BasicBlock, op: BinOp, span: Span, ty: ty::Ty<'tcx>,
+ pub fn build_binary_op(&mut self, mut block: BasicBlock,
+ op: BinOp, span: Span, ty: ty::Ty<'tcx>,
lhs: Operand<'tcx>, rhs: Operand<'tcx>) -> BlockAnd<Rvalue<'tcx>> {
let scope_id = self.innermost_scope_id();
let bool_ty = self.hir.bool_ty();
"arithmetic operation overflowed"
};
- block = self.with_cond(block, span, Operand::Consume(of), |this, block| {
- this.panic(block, msg, span);
- block
- });
+ let (of_block, ok_block) = self.build_cond_br(block, span, Operand::Consume(of));
+ self.panic(of_block, msg, span);
- block.and(Rvalue::Use(Operand::Consume(val)))
+ ok_block.and(Rvalue::Use(Operand::Consume(val)))
} else {
if ty.is_integral() && (op == BinOp::Div || op == BinOp::Rem) {
// Checking division and remainder is more complex, since we 1. always check
self.cfg.push_assign(block, scope_id, span, &is_zero,
Rvalue::BinaryOp(BinOp::Eq, rhs.clone(), zero));
- block = self.with_cond(block, span, Operand::Consume(is_zero), |this, block| {
- this.panic(block, zero_msg, span);
- block
- });
+ let (zero_block, ok_block) = self.build_cond_br(block, span,
+ Operand::Consume(is_zero));
+ self.panic(zero_block, zero_msg, span);
+
+ block = ok_block;
// We only need to check for the overflow in one case:
// MIN / -1, and only for signed values.
self.cfg.push_assign(block, scope_id, span, &of,
Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min));
- block = self.with_cond(block, span, Operand::Consume(of), |this, block| {
- this.panic(block, overflow_msg, span);
- block
- });
+ let (of_block, ok_block) = self.build_cond_br(block, span,
+ Operand::Consume(of));
+ self.panic(of_block, overflow_msg, span);
+
+ block = ok_block;
}
}