Initial implementation of typestate for closures.

There are still things not handled properly: relying on other preconditions
of upvars is likely to cause bad things to happen. We probably want to
disallow it.
This commit is contained in:
Michael Sullivan 2011-07-22 18:04:40 -07:00
parent 166d4f5fe9
commit 9ca0ce91bf
3 changed files with 31 additions and 13 deletions

View file

@ -486,6 +486,15 @@ fn constraints_expr(&ty::ctxt cx, @expr e) -> (@ty::constr)[] {
}
}
fn node_id_to_def_upvar_strict(&fn_ctxt cx, node_id id) -> def {
alt (freevars::def_lookup(cx.ccx.tcx, cx.id, id)) {
case (none) {
log_err "node_id_to_def: node_id " + int::str(id) + " has no def";
fail;
}
case (some(?d)) { ret d; }
}
}
fn node_id_to_def_strict(&ty::ctxt cx, node_id id) -> def {
alt (cx.def_map.find(id)) {
case (none) {

View file

@ -299,6 +299,18 @@ fn handle_update(&fn_ctxt fcx, &@expr parent,
}
}
fn handle_var(&fn_ctxt fcx, &pre_and_post rslt, node_id id, ident name) {
auto df = node_id_to_def_upvar_strict(fcx, id);
alt (df) {
case (def_local(?d_id)) {
auto i = bit_num(fcx, ninit(d_id.node, name));
use_var(fcx, d_id.node);
require_and_preserve(i, rslt);
}
case (_) {/* nothing to check */ }
}
}
/* Fills in annotations as a side effect. Does not rebuild the expr */
fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
auto enclosing = fcx.enclosing;
@ -337,17 +349,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
case (expr_path(?p)) {
auto rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
auto df = node_id_to_def_strict(fcx.ccx.tcx, e.id);
alt (df) {
case (def_local(?d_id)) {
auto i =
bit_num(fcx,
ninit(d_id.node, path_to_ident(fcx.ccx.tcx, p)));
use_var(fcx, d_id.node);
require_and_preserve(i, rslt);
}
case (_) {/* nothing to check */ }
}
handle_var(fcx, rslt, e.id, path_to_ident(fcx.ccx.tcx, p));
}
case (expr_self_method(?v)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_log(_, ?arg)) {
@ -367,7 +369,14 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
case (none) { clear_pp(expr_pp(fcx.ccx, e)); }
}
}
case (expr_fn(?f)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_fn(?f)) {
auto rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
auto upvars = freevars::get_freevar_uses(fcx.ccx.tcx, e.id);
for (node_id id in *upvars) {
handle_var(fcx, rslt, id, "upvar");
}
}
case (expr_block(?b)) {
find_pre_post_block(fcx, b);
auto p = block_pp(fcx.ccx, b);

View file

@ -208,7 +208,7 @@ fn find_pre_post_state_loop(&fn_ctxt fcx, prestate pres, &@local l,
fn gen_if_local(&fn_ctxt fcx, &poststate p, &@expr e) -> bool {
alt (e.node) {
case (expr_path(?pth)) {
alt (node_id_to_def(fcx.ccx, e.id)) {
alt (freevars::def_lookup(fcx.ccx.tcx, fcx.id, e.id)) {
case (some(def_local(?loc))) {
ret set_in_poststate_ident(fcx, loc.node,
path_to_ident(fcx.ccx.tcx, pth), p);