diff --git a/src/rustc/middle/tstate/states.rs b/src/rustc/middle/tstate/states.rs index f13e59aa3012..22380be87f56 100644 --- a/src/rustc/middle/tstate/states.rs +++ b/src/rustc/middle/tstate/states.rs @@ -550,7 +550,9 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { /* conservative approximation: if a loop contains a break or cont, we assume nothing about the poststate */ /* which is still unsound -- see [Break-unsound] */ - if has_nonlocal_exits(body) { + if may_break(body) { + /* Only do this if there are *breaks* not conts. + An infinite loop with conts is still an infinite loop. */ ret changed | set_poststate_ann(fcx.ccx, e.id, pres); } else { ret changed | set_poststate_ann(fcx.ccx, e.id, diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index 12bf9d6b9606..ecc70b6c6548 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -83,6 +83,22 @@ fn has_nonlocal_exits(b: ast::blk) -> bool { ret *has_exits; } +/* FIXME: copy/paste, yuck */ +fn may_break(b: ast::blk) -> bool { + let has_exits = @mutable false; + fn visit_expr(flag: @mutable bool, e: @ast::expr) { + alt e.node { + ast::expr_break { *flag = true; } + _ { } + } + } + let v = + visit::mk_simple_visitor(@{visit_expr: bind visit_expr(has_exits, _) + with *visit::default_simple_visitor()}); + visit::visit_block(b, (), v); + ret *has_exits; +} + fn local_rhs_span(l: @ast::local, def: span) -> span { alt l.node.init { some(i) { ret i.expr.span; } _ { ret def; } } }