Skip to content

Commit 3f3c9ca

Browse files
committed
Handle poststates of breaking loops correctly in typestate
The poststate should be one where all predicates are assumed false, rather than the unchanged prestate. Closes #2374
1 parent b30daa6 commit 3f3c9ca

File tree

3 files changed

+10
-25
lines changed

3 files changed

+10
-25
lines changed

src/rustc/middle/tstate/states.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ann::*;
22
import aux::*;
33
import tritv::{tritv_clone, tritv_set, ttrue};
44

5+
import syntax::print::pprust::block_to_str;
56
import bitvectors::*;
67
import pat_util::*;
78
import syntax::ast::*;
@@ -13,9 +14,6 @@ import driver::session::session;
1314
import std::map::hashmap;
1415

1516
fn forbid_upvar(fcx: fn_ctxt, rhs_id: node_id, sp: span, t: oper_type) {
16-
// fcx.ccx.tcx.sess.span_note(sp,
17-
// #fmt("forbid_upvar: checking. %?", t));
18-
1917
alt t {
2018
oper_move {
2119
alt local_node_id_to_def(fcx, rhs_id) {
@@ -457,12 +455,18 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
457455
let mut changed = set_prestate_ann(fcx.ccx, e.id, loop_pres)
458456
| find_pre_post_state_block(fcx, loop_pres, body);
459457
/* conservative approximation: if a loop contains a break
460-
or cont, we assume nothing about the poststate */
458+
or cont, we assume nothing about the poststate (so, we
459+
set all predicates to "don't know" */
461460
/* which is still unsound -- see [Break-unsound] */
462461
if may_break(body) {
463462
/* Only do this if there are *breaks* not conts.
464-
An infinite loop with conts is still an infinite loop. */
465-
ret changed | set_poststate_ann(fcx.ccx, e.id, pres);
463+
An infinite loop with conts is still an infinite loop.
464+
We assume all preds are FALSE, not '?' -- because in the
465+
worst case, the body could invalidate all preds and
466+
deinitialize everything before breaking */
467+
let post = empty_poststate(num_constrs);
468+
tritv::tritv_kill(post);
469+
ret changed | set_poststate_ann(fcx.ccx, e.id, post);
466470
} else {
467471
ret changed | set_poststate_ann(fcx.ccx, e.id,
468472
false_postcond(num_constrs));

src/rustc/middle/tstate/tritv.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -109,27 +109,14 @@ fn trit_or(a: trit, b: trit) -> trit {
109109
fn trit_and(a: trit, b: trit) -> trit {
110110
alt a {
111111
dont_care { b }
112-
113-
114-
115-
116112
// also seems wrong for case b = ttrue
117113
ttrue {
118114
alt b {
119115
dont_care { ttrue }
120-
121-
122-
123-
124116
// ??? Seems wrong
125117
ttrue {
126118
ttrue
127119
}
128-
129-
130-
131-
132-
133120
// false wins, since if something is uninit
134121
// on one path, we care
135122
// (Rationale: it's always safe to assume that
@@ -140,11 +127,6 @@ fn trit_and(a: trit, b: trit) -> trit {
140127
}
141128
}
142129
}
143-
144-
145-
146-
147-
148130
// Rationale: if it's uninit on one path,
149131
// we can consider it as uninit on all paths
150132
tfalse {

src/test/compile-fail/loop-pred-constraints.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// xfail-test
21
// https://github.com/mozilla/rust/issues/2374
32
// error-pattern:unsatisfied precondition constraint (for example, even(y
43

0 commit comments

Comments
 (0)