From 6bae4a763df95c436ce9f1286b1d593e67218932 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 3 Jan 2019 21:49:56 +0900 Subject: [PATCH 1/2] Fix unused_assignments false positive Make `continue` jump to the loop condition's `LiveNode` instead of one of the loop body. --- src/librustc/middle/liveness.rs | 11 ++++++----- src/test/ui/liveness/liveness-dead.rs | 9 +++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a78cf1a471b4b..71a104ba6e761 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -911,7 +911,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn compute(&mut self, body: &hir::Expr) -> LiveNode { - // if there is a `break` or `again` at the top level, then it's + // if there is a `break` or `continue` at the top level, then it's // effectively a return---this only occurs in `for` loops, // where the body is really a closure. @@ -1407,15 +1407,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { debug!("propagate_through_loop: using id for loop body {} {}", expr.id, self.ir.tcx.hir().node_to_pretty_string(body.id)); - let break_ln = succ; - let cont_ln = ln; - self.break_ln.insert(expr.id, break_ln); - self.cont_ln.insert(expr.id, cont_ln); + + self.break_ln.insert(expr.id, succ); let cond_ln = match kind { LoopLoop => ln, WhileLoop(ref cond) => self.propagate_through_expr(&cond, ln), }; + + self.cont_ln.insert(expr.id, cond_ln); + let body_ln = self.propagate_through_block(body, cond_ln); // repeat until fixed point is reached: diff --git a/src/test/ui/liveness/liveness-dead.rs b/src/test/ui/liveness/liveness-dead.rs index 7d420afde4b72..004663c85ee50 100644 --- a/src/test/ui/liveness/liveness-dead.rs +++ b/src/test/ui/liveness/liveness-dead.rs @@ -27,4 +27,13 @@ fn f5(mut x: i32) { x = 4; //~ ERROR: value assigned to `x` is never read } +// #22630 +fn f6() { + let mut done = false; + while !done { + done = true; // no error + continue; + } +} + fn main() {} From 069b0c410808c1d1d33b495e048b1186e9f8d57f Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 3 Jan 2019 23:20:44 +0900 Subject: [PATCH 2/2] Cleanup `for` loops are no longer closures. --- src/librustc/middle/liveness.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 71a104ba6e761..2ca823929fd38 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -911,17 +911,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn compute(&mut self, body: &hir::Expr) -> LiveNode { - // if there is a `break` or `continue` at the top level, then it's - // effectively a return---this only occurs in `for` loops, - // where the body is really a closure. - debug!("compute: using id for body, {}", self.ir.tcx.hir().node_to_pretty_string(body.id)); - let exit_ln = self.s.exit_ln; - - self.break_ln.insert(body.id, exit_ln); - self.cont_ln.insert(body.id, exit_ln); - // the fallthrough exit is only for those cases where we do not // explicitly return: let s = self.s; @@ -1024,19 +1015,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&e, succ) } - hir::ExprKind::Closure(.., blk_id, _, _) => { + hir::ExprKind::Closure(..) => { debug!("{} is an ExprKind::Closure", self.ir.tcx.hir().node_to_pretty_string(expr.id)); - // The next-node for a break is the successor of the entire - // loop. The next-node for a continue is the top of this loop. - let node = self.live_node(expr.hir_id, expr.span); - - let break_ln = succ; - let cont_ln = node; - self.break_ln.insert(blk_id.node_id, break_ln); - self.cont_ln.insert(blk_id.node_id, cont_ln); - // the construction of a closure itself is not important, // but we have to consider the closed over variables. let caps = self.ir.capture_info_map.get(&expr.id).cloned().unwrap_or_else(||