From 62bec714462129adcc622575d69db558b3750a6e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Jun 2019 10:08:20 +0100 Subject: [PATCH] Fix incorrect double assignment in MIR for while loops --- src/librustc_mir/build/expr/into.rs | 20 ++++++++++++++------ src/test/ui/nll/assign-while-to-immutable.rs | 11 +++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/nll/assign-while-to-immutable.rs diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index f70ecef0c25..dc74466e633 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 00000000000..c803321b508 --- /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 {}; +}