In typestate, consider infinite loops w/ conts to be infinite
If a loop { } contains a cont, that doesn't affect whether the entire loop diverges. Only breaks affect that. Fix that in typestate.
This commit is contained in:
parent
35400e13ad
commit
205cefdc6e
@ -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,
|
||||
|
@ -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; } }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user