diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index f70ecef0c254..dc74466e6330 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -184,15 +184,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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); + let false_block = this.cfg.start_new_block(); + let term = TerminatorKind::if_( + this.hir.tcx(), + cond, + body_block, + false_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); + // we have to do it + this.cfg.push_assign_unit(false_block, source_info, destination); + this.cfg.terminate( + false_block, + source_info, + TerminatorKind::Goto { target: exit_block }, + ); } else { body_block = this.cfg.start_new_block(); let diverge_cleanup = this.diverge_cleanup(); diff --git a/src/test/ui/nll/assign-while-to-immutable.rs b/src/test/ui/nll/assign-while-to-immutable.rs new file mode 100644 index 000000000000..c803321b5087 --- /dev/null +++ b/src/test/ui/nll/assign-while-to-immutable.rs @@ -0,0 +1,11 @@ +// We used to incorrectly assign to `x` twice when generating MIR for this +// function, preventing this from compiling. + +// check-pass + +fn main() { + let x = while false { + break; + }; + let y = 'l: while break 'l {}; +}