Skip to content

Commit d81d864

Browse files
committed
Handle sequential let semantics properly in typestate
Closes #824
1 parent 3ddb26e commit d81d864

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

src/comp/middle/tstate/pre_post_conditions.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,7 @@ import std::option;
44
import std::option::none;
55
import std::option::some;
66

7-
import tstate::ann::pre_and_post;
8-
import tstate::ann::get_post;
9-
import tstate::ann::postcond;
10-
import tstate::ann::true_precond;
11-
import tstate::ann::false_postcond;
12-
import tstate::ann::empty_poststate;
13-
import tstate::ann::require;
14-
import tstate::ann::require_and_preserve;
15-
import tstate::ann::union;
16-
import tstate::ann::intersect;
17-
import tstate::ann::pp_clone;
18-
import tstate::ann::empty_prestate;
19-
import tstate::ann::set_precondition;
20-
import tstate::ann::set_postcondition;
7+
import tstate::ann::*;
218
import aux::*;
229
import bitvectors::bit_num;
2310
import bitvectors::promises;
@@ -28,7 +15,7 @@ import bitvectors::declare_var;
2815
import bitvectors::gen_poststate;
2916
import bitvectors::relax_precond_block;
3017
import bitvectors::gen;
31-
import tritv::tritv_clone;
18+
import tritv::*;
3219
import syntax::ast::*;
3320
import syntax::visit;
3421
import std::map::new_int_hash;
@@ -591,6 +578,8 @@ fn find_pre_post_stmt(fcx: &fn_ctxt, s: &stmt) {
591578
stmt_decl(adecl, id) {
592579
alt adecl.node {
593580
decl_local(alocals) {
581+
let e_pp;
582+
let prev_pp = empty_pre_post(num_constraints(fcx.enclosing));
594583
for alocal: @local in alocals {
595584
alt alocal.node.init {
596585
some(an_init) {
@@ -611,7 +600,16 @@ fn find_pre_post_stmt(fcx: &fn_ctxt, s: &stmt) {
611600
}
612601

613602
for each pat: @pat in pat_bindings(alocal.node.pat) {
614-
let ident = alt pat.node { pat_bind(n) { n } };
603+
/* FIXME: This won't be necessary when typestate
604+
works well enough for pat_bindings to return a
605+
refinement-typed thing. */
606+
let ident = alt pat.node {
607+
pat_bind(n) { n }
608+
_ {
609+
fcx.ccx.tcx.sess.span_bug(pat.span,
610+
"Impossible LHS");
611+
}
612+
};
615613
alt p {
616614
some(p) {
617615
copy_in_postcond(fcx, id,
@@ -629,6 +627,29 @@ fn find_pre_post_stmt(fcx: &fn_ctxt, s: &stmt) {
629627
if an_init.op == init_move && is_path(an_init.expr) {
630628
forget_in_postcond(fcx, id, an_init.expr.id);
631629
}
630+
631+
/* Clear out anything that the previous initializer
632+
guaranteed */
633+
e_pp = expr_pp(fcx.ccx, an_init.expr);
634+
tritv_copy(prev_pp.precondition,
635+
seq_preconds(fcx, [prev_pp, e_pp]));
636+
/* Include the LHSs too, since those aren't in the
637+
postconds of the RHSs themselves */
638+
for each pat: @pat in pat_bindings(alocal.node.pat) {
639+
alt pat.node {
640+
pat_bind(n) {
641+
set_in_postcond(bit_num(fcx, ninit(pat.id, n)),
642+
prev_pp);
643+
}
644+
_ {
645+
fcx.ccx.tcx.sess.span_bug(pat.span,
646+
"Impossible LHS");
647+
}
648+
};
649+
}
650+
copy_pre_post_(fcx.ccx, id,
651+
prev_pp.precondition,
652+
prev_pp.postcondition);
632653
}
633654
none. {
634655
for each p: @pat in pat_bindings(alocal.node.pat) {

src/test/run-pass/multi-let.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
let x = 10, y = x;
3+
assert (y == 10);
4+
}

0 commit comments

Comments
 (0)