next = add_constraint(cx.tcx, sc, next, res_map);
}
+ /* Need to add constraints for args too, b/c they
+ can be deinitialized */
+ for a:arg in f.decl.inputs {
+ next = add_constraint(cx.tcx, respan(f_sp,
+ ninit(a.id, a.ident)),
+ next, res_map);
+ }
+
/* add the special i_diverge and i_return constraints
(see the type definition for auxiliary::fn_info for an explanation) */
{constrs: res_map,
num_constraints:
// add 2 to account for the i_return and i_diverge constraints
- vec::len(*cx.cs) + vec::len(f.decl.constraints) + 2u,
+ vec::len(*cx.cs) + vec::len(f.decl.constraints)
+ + vec::len(f.decl.inputs) + 2u,
cf: f.decl.cf,
i_return: ninit(id, name),
i_diverge: ninit(diverges_id, diverges_name),
}
}
+/* FIXME: Can't deinitialize an upvar -- tests for that? */
fn handle_var(fcx: &fn_ctxt, rslt: &pre_and_post, id: node_id, name: ident) {
let df = node_id_to_def_upvar_strict(fcx, id);
alt df {
- def_local(d_id) {
+ def_local(d_id) | def_arg(d_id) {
let i = bit_num(fcx, ninit(d_id.node, name));
use_var(fcx, d_id.node);
require_and_preserve(i, rslt);
fn forget_args_moved_in(fcx: &fn_ctxt, parent: &@expr,
modes: &[ty::mode],
operands: &[@expr]) {
- let i = 0;
+ let i = 0u;
for mode: ty::mode in modes {
if mode == ty::mo_move {
forget_in_postcond(fcx, parent.id, operands.(i).id);
}
- i += 1;
+ i += 1u;
}
}
let nv = num_constraints(fcx.enclosing);
fn do_one_(fcx: fn_ctxt, s: &@stmt) {
find_pre_post_stmt(fcx, *s);
- log "pre_post for stmt:";
- log_stmt(*s);
- log "is:";
- log_pp(stmt_pp(fcx.ccx, *s));
+/*
+ log_err "pre_post for stmt:";
+ log_stmt_err(*s);
+ log_err "is:";
+ log_pp_err(stmt_pp(fcx.ccx, *s));
+*/
}
for s: @stmt in b.node.stmts { do_one_(fcx, s); }
fn do_inner_(fcx: fn_ctxt, e: &@expr) { find_pre_post_expr(fcx, e); }
id: node_id, ops: &[init_op], bs: &[@expr],
cf: controlflow) -> bool {
let changed = find_pre_post_state_expr(fcx, pres, a);
+ // FIXME: This could be a typestate constraint
if vec::len(bs) != vec::len(ops) {
fcx.ccx.tcx.sess.span_bug(a.span,
#fmt("mismatched arg lengths: \
fn find_pre_post_state_stmt(fcx: &fn_ctxt, pres: &prestate, s: @stmt)
-> bool {
let stmt_ann = stmt_to_ann(fcx.ccx, *s);
+
/*
log_err ("[" + fcx.name + "]");
log_err "*At beginning: stmt = ";
// This ensures that intersect works correctly.
kill_all_prestate(fcx, f.body.node.id);
- // Instantiate any constraints on the arguments so we can use them
+ // Arguments start out initialized
let block_pre = block_prestate(fcx.ccx, f.body);
+ for a:arg in f.decl.inputs {
+ set_in_prestate_constr(fcx, ninit(a.id, a.ident), block_pre);
+ }
+
+ // Instantiate any constraints on the arguments so we can use them
let tsc;
for c: @constr in f.decl.constraints {
tsc = ast_constr_to_ts_constr(fcx.ccx.tcx, f.decl.inputs, c);
--- /dev/null
+// error-pattern: Unsatisfied precondition constraint
+fn send<~T>(ch : _chan<T>, data : -T) {
+ log ch;
+ log data;
+ fail;
+}
+type _chan<T> = int;
+
+// Tests that "log message;" is flagged as using
+// message after the send deinitializes it
+fn test00_start(ch: _chan<int>, message: int, count: int) {
+ send(ch, message);
+ log message;
+}
+
+fn main() {
+ fail;
+}
\ No newline at end of file