Skip to content

Commit f023f82

Browse files
committed
Track arguments in typestate
Add the infrastructure for arguments -- as well as local vars -- to be deinitialized with move-mode calls. Address Issue #819
1 parent 69d4838 commit f023f82

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

src/comp/middle/tstate/collect_locals.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ fn mk_fn_info(ccx: &crate_ctxt, f: &_fn, tp: &[ty_param], f_sp: &span,
109109
next = add_constraint(cx.tcx, sc, next, res_map);
110110
}
111111

112+
/* Need to add constraints for args too, b/c they
113+
can be deinitialized */
114+
for a:arg in f.decl.inputs {
115+
next = add_constraint(cx.tcx, respan(f_sp,
116+
ninit(a.id, a.ident)),
117+
next, res_map);
118+
}
119+
112120
/* add the special i_diverge and i_return constraints
113121
(see the type definition for auxiliary::fn_info for an explanation) */
114122

@@ -127,7 +135,8 @@ fn mk_fn_info(ccx: &crate_ctxt, f: &_fn, tp: &[ty_param], f_sp: &span,
127135
{constrs: res_map,
128136
num_constraints:
129137
// add 2 to account for the i_return and i_diverge constraints
130-
vec::len(*cx.cs) + vec::len(f.decl.constraints) + 2u,
138+
vec::len(*cx.cs) + vec::len(f.decl.constraints)
139+
+ vec::len(f.decl.inputs) + 2u,
131140
cf: f.decl.cf,
132141
i_return: ninit(id, name),
133142
i_diverge: ninit(diverges_id, diverges_name),

src/comp/middle/tstate/pre_post_conditions.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,11 @@ fn handle_update(fcx: &fn_ctxt, parent: &@expr, lhs: &@expr, rhs: &@expr,
303303
}
304304
}
305305

306+
/* FIXME: Can't deinitialize an upvar -- tests for that? */
306307
fn handle_var(fcx: &fn_ctxt, rslt: &pre_and_post, id: node_id, name: ident) {
307308
let df = node_id_to_def_upvar_strict(fcx, id);
308309
alt df {
309-
def_local(d_id) {
310+
def_local(d_id) | def_arg(d_id) {
310311
let i = bit_num(fcx, ninit(d_id.node, name));
311312
use_var(fcx, d_id.node);
312313
require_and_preserve(i, rslt);
@@ -318,12 +319,12 @@ fn handle_var(fcx: &fn_ctxt, rslt: &pre_and_post, id: node_id, name: ident) {
318319
fn forget_args_moved_in(fcx: &fn_ctxt, parent: &@expr,
319320
modes: &[ty::mode],
320321
operands: &[@expr]) {
321-
let i = 0;
322+
let i = 0u;
322323
for mode: ty::mode in modes {
323324
if mode == ty::mo_move {
324325
forget_in_postcond(fcx, parent.id, operands.(i).id);
325326
}
326-
i += 1;
327+
i += 1u;
327328
}
328329
}
329330

@@ -672,10 +673,12 @@ fn find_pre_post_block(fcx: &fn_ctxt, b: blk) {
672673
let nv = num_constraints(fcx.enclosing);
673674
fn do_one_(fcx: fn_ctxt, s: &@stmt) {
674675
find_pre_post_stmt(fcx, *s);
675-
log "pre_post for stmt:";
676-
log_stmt(*s);
677-
log "is:";
678-
log_pp(stmt_pp(fcx.ccx, *s));
676+
/*
677+
log_err "pre_post for stmt:";
678+
log_stmt_err(*s);
679+
log_err "is:";
680+
log_pp_err(stmt_pp(fcx.ccx, *s));
681+
*/
679682
}
680683
for s: @stmt in b.node.stmts { do_one_(fcx, s); }
681684
fn do_inner_(fcx: fn_ctxt, e: &@expr) { find_pre_post_expr(fcx, e); }

src/comp/middle/tstate/states.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ fn find_pre_post_state_call(fcx: &fn_ctxt, pres: &prestate, a: &@expr,
165165
id: node_id, ops: &[init_op], bs: &[@expr],
166166
cf: controlflow) -> bool {
167167
let changed = find_pre_post_state_expr(fcx, pres, a);
168+
// FIXME: This could be a typestate constraint
168169
if vec::len(bs) != vec::len(ops) {
169170
fcx.ccx.tcx.sess.span_bug(a.span,
170171
#fmt("mismatched arg lengths: \
@@ -605,6 +606,7 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) ->
605606
fn find_pre_post_state_stmt(fcx: &fn_ctxt, pres: &prestate, s: @stmt)
606607
-> bool {
607608
let stmt_ann = stmt_to_ann(fcx.ccx, *s);
609+
608610
/*
609611
log_err ("[" + fcx.name + "]");
610612
log_err "*At beginning: stmt = ";
@@ -727,8 +729,13 @@ fn find_pre_post_state_fn(fcx: &fn_ctxt, f: &_fn) -> bool {
727729
// This ensures that intersect works correctly.
728730
kill_all_prestate(fcx, f.body.node.id);
729731

730-
// Instantiate any constraints on the arguments so we can use them
732+
// Arguments start out initialized
731733
let block_pre = block_prestate(fcx.ccx, f.body);
734+
for a:arg in f.decl.inputs {
735+
set_in_prestate_constr(fcx, ninit(a.id, a.ident), block_pre);
736+
}
737+
738+
// Instantiate any constraints on the arguments so we can use them
732739
let tsc;
733740
for c: @constr in f.decl.constraints {
734741
tsc = ast_constr_to_ts_constr(fcx.ccx.tcx, f.decl.inputs, c);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// error-pattern: Unsatisfied precondition constraint
2+
fn send<~T>(ch : _chan<T>, data : -T) {
3+
log ch;
4+
log data;
5+
fail;
6+
}
7+
type _chan<T> = int;
8+
9+
// Tests that "log message;" is flagged as using
10+
// message after the send deinitializes it
11+
fn test00_start(ch: _chan<int>, message: int, count: int) {
12+
send(ch, message);
13+
log message;
14+
}
15+
16+
fn main() {
17+
fail;
18+
}

0 commit comments

Comments
 (0)