join_block.unit()
}
- ExprKind::Loop {
- condition: opt_cond_expr,
- body,
- } => {
- // [block] --> [loop_block] -/eval. cond./-> [loop_block_end] -1-> [exit_block]
- // ^ |
- // | 0
- // | |
- // | v
- // [body_block_end] <-/eval. body/-- [body_block]
- //
- // If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
- //
+ ExprKind::Loop { body } => {
// [block]
// |
// [loop_block] -> [body_block] -/eval. body/-> [body_block_end]
destination.clone(),
move |this| {
// conduct the test, if necessary
- let body_block;
- if let Some(cond_expr) = opt_cond_expr {
- let loop_block_end;
- let cond = unpack!(
- loop_block_end = this.as_local_operand(loop_block, cond_expr)
- );
- body_block = this.cfg.start_new_block();
- let term =
- TerminatorKind::if_(this.hir.tcx(), cond, body_block, exit_block);
- this.cfg.terminate(loop_block_end, source_info, term);
-
- // if the test is false, there's no `break` to assign `destination`, so
- // we have to do it; this overwrites any `break`-assigned value but it's
- // always `()` anyway
- this.cfg
- .push_assign_unit(exit_block, source_info, destination);
- } else {
- body_block = this.cfg.start_new_block();
- let diverge_cleanup = this.diverge_cleanup();
- this.cfg.terminate(
- loop_block,
- source_info,
- TerminatorKind::FalseUnwind {
- real_target: body_block,
- unwind: Some(diverge_cleanup),
- },
- )
- }
+ let body_block = this.cfg.start_new_block();
+ let diverge_cleanup = this.diverge_cleanup();
+ this.cfg.terminate(
+ loop_block,
+ source_info,
+ TerminatorKind::FalseUnwind {
+ real_target: body_block,
+ unwind: Some(diverge_cleanup),
+ },
+ );
// The “return” value of the loop body must always be an unit. We therefore
// introduce a unit temporary as the destination for the loop body.
is_user_variable: None,
is_block_tail: None,
});
- let ptr_temp = Place::Base(PlaceBase::Local(ptr_temp));
+ let ptr_temp = Place::from(ptr_temp);
let block = unpack!(this.into(&ptr_temp, block, ptr));
this.into(&ptr_temp.deref(), block, val)
} else {