Track spans for each local variable in typestate

This lets us print better messages in situations with name
shadowing.
This commit is contained in:
Tim Chevalier 2011-05-26 16:02:25 -07:00
parent 250643c549
commit 4f792f2dbb
9 changed files with 187 additions and 104 deletions

View file

@ -91,14 +91,15 @@ fn collect_ids_decl(&@decl d, @vec[uint] res) -> () {
}
}
fn node_ids_in_fn(&_fn f, &ident i, &def_id d, &ann a, @vec[uint] res) -> () {
fn node_ids_in_fn(&_fn f, &span sp, &ident i, &def_id d, &ann a,
@vec[uint] res) -> () {
auto collect_ids = walk::default_visitor();
collect_ids = rec(visit_expr_pre = bind collect_ids_expr(_,res),
visit_block_pre = bind collect_ids_block(_,res),
visit_stmt_pre = bind collect_ids_stmt(_,res),
visit_decl_pre = bind collect_ids_decl(_,res)
with collect_ids);
walk::walk_fn(collect_ids, f, i, d, a);
walk::walk_fn(collect_ids, f, sp, i, d, a);
}
fn init_vecs(&crate_ctxt ccx, @vec[uint] node_ids, uint len) -> () {
@ -108,23 +109,24 @@ fn init_vecs(&crate_ctxt ccx, @vec[uint] node_ids, uint len) -> () {
}
}
fn visit_fn(&crate_ctxt ccx, uint num_locals, &_fn f, &ident i,
&def_id d, &ann a) -> () {
fn visit_fn(&crate_ctxt ccx, uint num_locals, &_fn f,
&span sp, &ident i, &def_id d, &ann a) -> () {
let vec[uint] node_ids_ = [];
let @vec[uint] node_ids = @node_ids_;
node_ids_in_fn(f, i, d, a, node_ids);
node_ids_in_fn(f, sp, i, d, a, node_ids);
init_vecs(ccx, node_ids, num_locals);
}
fn annotate_in_fn(&crate_ctxt ccx, &_fn f, &ident i, &def_id f_id, &ann a)
fn annotate_in_fn(&crate_ctxt ccx, &_fn f, &span sp, &ident i,
&def_id f_id, &ann a)
-> () {
auto f_info = get_fn_info(ccx, f_id);
visit_fn(ccx, num_locals(f_info), f, i, f_id, a);
visit_fn(ccx, num_locals(f_info), f, sp, i, f_id, a);
}
fn annotate_crate(&crate_ctxt ccx, &crate crate) -> () {
auto do_ann = walk::default_visitor();
do_ann = rec(visit_fn_pre = bind annotate_in_fn(ccx,_,_,_,_)
do_ann = rec(visit_fn_pre = bind annotate_in_fn(ccx,_,_,_,_,_)
with do_ann);
walk::walk_crate(do_ann, crate);
}

View file

@ -18,7 +18,6 @@ import front::ast::expr_path;
import front::ast::ident;
import front::ast::controlflow;
import front::ast::ann;
import front::ast::ts_ann;
import front::ast::stmt;
import front::ast::expr;
import front::ast::block;
@ -54,26 +53,60 @@ import tstate::ann::extend_prestate;
import tstate::ann::extend_poststate;
import tstate::ann::set_precondition;
import tstate::ann::set_postcondition;
import tstate::ann::ts_ann;
import util::common::istr;
/* logging funs */
fn bitv_to_str(fn_info enclosing, bitv::t v) -> str {
auto s = "";
fn def_id_to_str(def_id d) -> str {
ret (istr(d._0) + "," + istr(d._1));
}
for each (@tup(def_id, tup(uint, ident)) p in enclosing.vars.items()) {
if (bitv::get(v, p._1._0)) {
s += " " + p._1._1 + " ";
}
fn bitv_to_str(fn_ctxt fcx, bitv::t v) -> str {
auto s = "";
auto comma = false;
for each (@tup(def_id, var_info) p in fcx.enclosing.vars.items()) {
if (bitv::get(v, p._1.bit_num)) {
s += (if (comma) { ", " } else { comma = true; "" })
+ p._1.name + " [" + fcx.ccx.tcx.sess.span_str(p._1.sp) + "]";
}
}
ret s;
}
fn log_bitv(fn_info enclosing, bitv::t v) {
log(bitv_to_str(enclosing, v));
fn log_bitv(fn_ctxt fcx, bitv::t v) {
log(bitv_to_str(fcx, v));
}
fn log_bitv_err(fn_info enclosing, bitv::t v) {
log_err(bitv_to_str(enclosing, v));
fn first_difference_string(&fn_ctxt fcx, &bitv::t expected,
&bitv::t actual) -> str {
let str s = "";
auto done = false;
for each (@tup(def_id, var_info) p in fcx.enclosing.vars.items()) {
if (!done) {
if (bitv::get(expected, p._1.bit_num) &&
!bitv::get(actual, p._1.bit_num)) {
/*
for fun, try either:
* "ret s" after the assignment to s
or
* using break here
*/
s = (p._1.name + " ["
+ fcx.ccx.tcx.sess.span_str(p._1.sp) + "]");
done = true;
}
}
}
ret s;
}
fn log_bitv_err(fn_ctxt fcx, bitv::t v) {
log_err(bitv_to_str(fcx, v));
}
fn tos (vec[uint] v) -> str {
@ -152,8 +185,10 @@ fn print_idents(vec[ident] idents) -> () {
/**********************************************************************/
/* mapping from variable name (def_id is assumed to be for a local
variable in a given function) to bit number
(also remembers the ident for error-logging purposes) */
type var_info = tup(uint, ident);
(also remembers the ident and span for error-logging purposes) */
type var_info = rec(uint bit_num,
ident name,
span sp);
type fn_info = rec(@std::map::hashmap[def_id, var_info] vars,
controlflow cf);

View file

@ -33,7 +33,7 @@ import tstate::ann::clear_in_poststate;
fn bit_num(def_id v, fn_info m) -> uint {
assert (m.vars.contains_key(v));
ret m.vars.get(v)._0;
ret m.vars.get(v).bit_num;
}
fn promises(&poststate p, def_id v, fn_info m) -> bool {
@ -44,14 +44,14 @@ fn promises(&poststate p, def_id v, fn_info m) -> bool {
// return the precondition for evaluating each expr in order.
// So, if e0's post is {x} and e1's pre is {x, y, z}, the entire
// precondition shouldn't include x.
fn seq_preconds(fn_info enclosing, vec[pre_and_post] pps) -> precond {
fn seq_preconds(fn_ctxt fcx, vec[pre_and_post] pps) -> precond {
let uint sz = len[pre_and_post](pps);
let uint num_vars = num_locals(enclosing);
let uint num_vars = num_locals(fcx.enclosing);
if (sz >= 1u) {
auto first = pps.(0);
assert (pps_len(first) == num_vars);
let precond rest = seq_preconds(enclosing,
let precond rest = seq_preconds(fcx,
slice[pre_and_post](pps, 1u, sz));
difference(rest, first.postcondition);
auto res = clone(first.precondition);
@ -59,11 +59,11 @@ fn seq_preconds(fn_info enclosing, vec[pre_and_post] pps) -> precond {
log("seq_preconds:");
log("first.postcondition =");
log_bitv(enclosing, first.postcondition);
log_bitv(fcx, first.postcondition);
log("rest =");
log_bitv(enclosing, rest);
log_bitv(fcx, rest);
log("returning");
log_bitv(enclosing, res);
log_bitv(fcx, res);
ret res;
}
@ -118,14 +118,14 @@ fn intersect_postconds(&vec[postcond] pcs) -> postcond {
fn gen(&fn_ctxt fcx, &ann a, def_id id) -> bool {
log "gen";
assert (fcx.enclosing.vars.contains_key(id));
let uint i = (fcx.enclosing.vars.get(id))._0;
let uint i = (fcx.enclosing.vars.get(id)).bit_num;
ret set_in_postcond(i, (ann_to_ts_ann(fcx.ccx, a)).conditions);
}
fn declare_var(&fn_info enclosing, def_id id, prestate pre)
-> prestate {
assert (enclosing.vars.contains_key(id));
let uint i = (enclosing.vars.get(id))._0;
let uint i = (enclosing.vars.get(id)).bit_num;
auto res = clone(pre);
relax_prestate(i, res);
ret res;
@ -134,14 +134,14 @@ fn declare_var(&fn_info enclosing, def_id id, prestate pre)
fn gen_poststate(&fn_ctxt fcx, &ann a, def_id id) -> bool {
log "gen_poststate";
assert (fcx.enclosing.vars.contains_key(id));
let uint i = (fcx.enclosing.vars.get(id))._0;
let uint i = (fcx.enclosing.vars.get(id)).bit_num;
ret set_in_poststate(i, (ann_to_ts_ann(fcx.ccx, a)).states);
}
fn kill_poststate(&fn_ctxt fcx, &ann a, def_id id) -> bool {
log "kill_poststate";
assert (fcx.enclosing.vars.contains_key(id));
let uint i = (fcx.enclosing.vars.get(id))._0;
let uint i = (fcx.enclosing.vars.get(id)).bit_num;
ret clear_in_poststate(i, (ann_to_ts_ann(fcx.ccx, a)).states);
}

View file

@ -53,6 +53,7 @@ import aux::stmt_to_ann;
import aux::num_locals;
import aux::fixed_point_states;
import aux::bitv_to_str;
import aux::first_difference_string;
import util::common::ty_to_str;
import util::common::log_stmt_err;
@ -70,12 +71,14 @@ fn check_states_expr(&fn_ctxt fcx, @expr e) -> () {
if (!implies(pres, prec)) {
auto s = "";
s += ("Unsatisfied precondition constraint for expression:\n");
auto diff = first_difference_string(fcx, prec, pres);
s += ("Unsatisfied precondition constraint (for example, "
+ diff + ") for expression:\n");
s += util::common::expr_to_str(e);
s += ("\nPrecondition:\n");
s += bitv_to_str(fcx.enclosing, prec);
s += bitv_to_str(fcx, prec);
s += ("\nPrestate:\n");
s += bitv_to_str(fcx.enclosing, pres);
s += bitv_to_str(fcx, pres);
fcx.ccx.tcx.sess.span_err(e.span, s);
}
}
@ -96,12 +99,14 @@ fn check_states_stmt(&fn_ctxt fcx, &stmt s) -> () {
if (!implies(pres, prec)) {
auto ss = "";
ss += ("Unsatisfied precondition constraint for statement:\n");
auto diff = first_difference_string(fcx, prec, pres);
ss += ("Unsatisfied precondition constraint (for example, "
+ diff + ") for statement:\n");
ss += util::common::stmt_to_str(s);
ss += ("\nPrecondition:\n");
ss += bitv_to_str(fcx.enclosing, prec);
ss += bitv_to_str(fcx, prec);
ss += ("\nPrestate: \n");
ss += bitv_to_str(fcx.enclosing, pres);
ss += bitv_to_str(fcx, pres);
fcx.ccx.tcx.sess.span_err(s.span, ss);
}
}
@ -162,7 +167,8 @@ fn check_fn_states(&fn_ctxt fcx, &_fn f, &ann a) -> () {
check_states_against_conditions(fcx, f, a);
}
fn fn_states(&crate_ctxt ccx, &_fn f, &ident i, &def_id id, &ann a) -> () {
fn fn_states(&crate_ctxt ccx, &_fn f, &span sp, &ident i,
&def_id id, &ann a) -> () {
/* Look up the var-to-bit-num map for this function */
assert (ccx.fm.contains_key(id));
auto f_info = ccx.fm.get(id);
@ -171,6 +177,8 @@ fn fn_states(&crate_ctxt ccx, &_fn f, &ident i, &def_id id, &ann a) -> () {
check_fn_states(fcx, f, a);
}
fn check_crate(ty::ctxt cx, @crate crate) -> () {
let crate_ctxt ccx = new_crate_ctxt(cx);
@ -182,14 +190,14 @@ fn check_crate(ty::ctxt cx, @crate crate) -> () {
/* Compute the pre and postcondition for every subexpression */
auto do_pre_post = walk::default_visitor();
do_pre_post = rec(visit_fn_pre = bind fn_pre_post(ccx,_,_,_,_)
do_pre_post = rec(visit_fn_pre = bind fn_pre_post(ccx,_,_,_,_,_)
with do_pre_post);
walk::walk_crate(do_pre_post, *crate);
/* Check the pre- and postcondition against the pre- and poststate
for every expression */
auto do_states = walk::default_visitor();
do_states = rec(visit_fn_pre = bind fn_states(ccx,_,_,_,_)
do_states = rec(visit_fn_pre = bind fn_states(ccx,_,_,_,_,_)
with do_states);
walk::walk_crate(do_states, *crate);
}

View file

@ -23,6 +23,7 @@ import front::ast::ident;
import middle::walk::walk_crate;
import middle::walk::walk_fn;
import middle::walk::ast_visitor;
import front::ast::span;
import aux::fn_info;
import aux::var_info;
@ -31,39 +32,44 @@ import aux::crate_ctxt;
import util::common::new_def_hash;
import util::common::uistr;
type identifier = rec(ident name, def_id id, span sp);
fn var_is_local(def_id v, fn_info m) -> bool {
ret (m.vars.contains_key(v));
}
fn collect_local(&@vec[tup(ident, def_id)] vars, &@decl d) -> () {
fn collect_local(&@vec[identifier] vars, &@decl d) -> () {
alt (d.node) {
case (decl_local(?loc)) {
log("collect_local: pushing " + loc.ident);
vec::push[tup(ident, def_id)](*vars, tup(loc.ident, loc.id));
vec::push[identifier](*vars, rec(name=loc.ident,
id=loc.id,
sp=d.span));
}
case (_) { ret; }
}
}
fn find_locals(&_fn f, &ident i, &def_id d, &ann a)
-> @vec[tup(ident,def_id)] {
auto res = @vec::alloc[tup(ident,def_id)](0u);
fn find_locals(&_fn f, &span sp, &ident i, &def_id d, &ann a)
-> @vec[identifier] {
auto res = @vec::alloc[identifier](0u);
auto visitor = walk::default_visitor();
visitor = rec(visit_decl_pre=bind collect_local(res,_) with visitor);
walk_fn(visitor, f, i, d, a);
walk_fn(visitor, f, sp, i, d, a);
ret res;
}
fn add_var(def_id v, ident nm, uint next, fn_info tbl) -> uint {
fn add_var(def_id v, span sp, ident nm, uint next, fn_info tbl) -> uint {
log(nm + " |-> " + util::common::uistr(next));
tbl.vars.insert(v, tup(next,nm));
tbl.vars.insert(v, rec(bit_num=next, name=nm, sp=sp));
ret (next + 1u);
}
/* builds a table mapping each local var defined in f
to a bit number in the precondition/postcondition vectors */
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &ident f_name, &def_id f_id, &ann a)
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &span f_sp,
&ident f_name, &def_id f_id, &ann a)
-> () {
auto res = rec(vars=@new_def_hash[var_info](),
cf=f.decl.cf);
@ -73,15 +79,15 @@ fn mk_fn_info(&crate_ctxt ccx, &_fn f, &ident f_name, &def_id f_id, &ann a)
/* ignore args, which we know are initialized;
just collect locally declared vars */
let @vec[tup(ident,def_id)] locals = find_locals(f, f_name, f_id, a);
for (tup(ident,def_id) p in *locals) {
next = add_var(p._1, p._0, next, res);
let @vec[identifier] locals = find_locals(f, f_sp, f_name, f_id, a);
for (identifier p in *locals) {
next = add_var(p.id, p.sp, p.name, next, res);
}
/* add a pseudo-entry for the function's return value
we can safely use the function's name itself for this purpose */
add_var(f_id, f_name, next, res);
add_var(f_id, f_sp, f_name, next, res);
log(f_name + " has " + uistr(vec::len[tup(ident, def_id)](*locals))
log(f_name + " has " + uistr(vec::len[identifier](*locals))
+ " locals");
ccx.fm.insert(f_id, res);
@ -92,7 +98,7 @@ fn mk_fn_info(&crate_ctxt ccx, &_fn f, &ident f_name, &def_id f_id, &ann a)
to bit number) */
fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) -> () {
let ast_visitor vars_visitor = walk::default_visitor();
vars_visitor = rec(visit_fn_pre=bind mk_fn_info(ccx,_,_,_,_)
vars_visitor = rec(visit_fn_pre=bind mk_fn_info(ccx,_,_,_,_,_)
with vars_visitor);
walk_crate(vars_visitor, *c);

View file

@ -151,6 +151,8 @@ import util::common::log_expr_err;
import util::common::log_block_err;
import util::common::log_block;
import front::ast::span;
fn find_pre_post_mod(&_mod m) -> _mod {
log("implement find_pre_post_mod!");
fail;
@ -238,7 +240,7 @@ fn find_pre_post_exprs(&fn_ctxt fcx, &vec[@expr] args, ann a) {
auto pps = vec::map[@expr, pre_and_post](g, args);
auto h = get_post;
set_pre_and_post(fcx.ccx, a, seq_preconds(enclosing, pps),
set_pre_and_post(fcx.ccx, a, seq_preconds(fcx, pps),
union_postconds
(nv, (vec::map[pre_and_post, postcond](h, pps))));
}
@ -249,8 +251,7 @@ fn find_pre_post_loop(&fn_ctxt fcx, &@decl d, &@expr index,
find_pre_post_block(fcx, body);
log("222");
auto loop_precond = declare_var(fcx.enclosing, decl_lhs(d),
seq_preconds(fcx.enclosing, [expr_pp(fcx.ccx, index),
block_pp(fcx.ccx, body)]));
seq_preconds(fcx, [expr_pp(fcx.ccx, index), block_pp(fcx.ccx, body)]));
auto loop_postcond = intersect_postconds
([expr_postcond(fcx.ccx, index), block_postcond(fcx.ccx, body)]);
set_pre_and_post(fcx.ccx, a, loop_precond, loop_postcond);
@ -259,13 +260,18 @@ fn find_pre_post_loop(&fn_ctxt fcx, &@decl d, &@expr index,
fn gen_if_local(&fn_ctxt fcx, @expr lhs, @expr rhs,
&ann larger_ann, &ann new_var) -> () {
alt (ann_to_def(fcx.ccx, new_var)) {
case (some[def](def_local(?d_id))) {
find_pre_post_expr(fcx, rhs);
auto p = expr_pp(fcx.ccx, rhs);
set_pre_and_post(fcx.ccx, larger_ann,
p.precondition, p.postcondition);
gen(fcx, larger_ann, d_id);
}
case (some[def](?d)) {
alt (d) {
case (def_local(?d_id)) {
find_pre_post_expr(fcx, rhs);
auto p = expr_pp(fcx.ccx, rhs);
set_pre_and_post(fcx.ccx, larger_ann,
p.precondition, p.postcondition);
gen(fcx, larger_ann, d_id);
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], larger_ann); }
}
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], larger_ann); }
}
}
@ -401,7 +407,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
alt (maybe_alt) {
case (none[@expr]) {
log "333";
auto precond_res = seq_preconds(enclosing,
auto precond_res = seq_preconds(fcx,
[expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
set_pre_and_post(fcx.ccx, a, precond_res,
@ -411,17 +417,16 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
find_pre_post_expr(fcx, altern);
log "444";
auto precond_true_case =
seq_preconds(enclosing,
[expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
seq_preconds(fcx, [expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
auto postcond_true_case = union_postconds
(num_local_vars,
[expr_postcond(fcx.ccx, antec),
block_postcond(fcx.ccx, conseq)]);
log "555";
auto precond_false_case = seq_preconds
(enclosing,
[expr_pp(fcx.ccx, antec), expr_pp(fcx.ccx, altern)]);
(fcx, [expr_pp(fcx.ccx, antec),
expr_pp(fcx.ccx, altern)]);
auto postcond_false_case = union_postconds
(num_local_vars,
[expr_postcond(fcx.ccx, antec),
@ -456,7 +461,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
find_pre_post_block(fcx, body);
log "666";
set_pre_and_post(fcx.ccx, a,
seq_preconds(enclosing,
seq_preconds(fcx,
[expr_pp(fcx.ccx, test),
block_pp(fcx.ccx, body)]),
intersect_postconds([expr_postcond(fcx.ccx, test),
@ -476,8 +481,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
}
log "777";
set_pre_and_post(fcx.ccx, a,
seq_preconds(enclosing,
set_pre_and_post(fcx.ccx, a, seq_preconds(fcx,
[block_pp(fcx.ccx, body),
expr_pp(fcx.ccx, test)]),
loop_postcond);
@ -499,19 +503,17 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
}
auto f = bind do_an_alt(fcx, _);
auto alt_pps = vec::map[arm, pre_and_post](f, alts);
fn combine_pp(pre_and_post antec,
fn_info enclosing, &pre_and_post pp,
fn combine_pp(pre_and_post antec, fn_ctxt fcx, &pre_and_post pp,
&pre_and_post next) -> pre_and_post {
log "777";
union(pp.precondition, seq_preconds(enclosing,
[antec, next]));
union(pp.precondition, seq_preconds(fcx, [antec, next]));
intersect(pp.postcondition, next.postcondition);
ret pp;
}
auto antec_pp = pp_clone(expr_pp(fcx.ccx, e));
auto e_pp = @rec(precondition=empty_prestate(num_local_vars),
postcondition=false_postcond(num_local_vars));
auto g = bind combine_pp(antec_pp, fcx.enclosing, _, _);
auto g = bind combine_pp(antec_pp, fcx, _, _);
auto alts_overall_pp = vec::foldl[pre_and_post, pre_and_post]
(g, e_pp, alt_pps);
@ -668,7 +670,7 @@ fn find_pre_post_block(&fn_ctxt fcx, block b) -> () {
plus_option[pre_and_post](pps,
option::map[@expr, pre_and_post](g, b.node.expr));
auto block_precond = seq_preconds(fcx.enclosing, pps);
auto block_precond = seq_preconds(fcx, pps);
auto h = get_post;
auto postconds = vec::map[pre_and_post, postcond](h, pps);
/* A block may be empty, so this next line ensures that the postconds
@ -687,7 +689,8 @@ fn find_pre_post_fn(&fn_ctxt fcx, &_fn f) -> () {
find_pre_post_block(fcx, f.body);
}
fn fn_pre_post(crate_ctxt ccx, &_fn f, &ident i, &def_id id, &ann a) -> () {
fn fn_pre_post(crate_ctxt ccx, &_fn f, &span sp, &ident i, &def_id id,
&ann a) -> () {
assert (ccx.fm.contains_key(id));
auto fcx = rec(enclosing=ccx.fm.get(id),
id=id, name=i, ccx=ccx);
@ -704,4 +707,3 @@ fn fn_pre_post(crate_ctxt ccx, &_fn f, &ident i, &def_id id, &ann a) -> () {
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//

View file

@ -204,8 +204,10 @@ fn find_pre_post_state_loop(&fn_ctxt fcx, prestate pres, &@decl d,
fn gen_if_local(&fn_ctxt fcx, &ann a_new_var, &ann a) -> bool {
alt (ann_to_def(fcx.ccx, a_new_var)) {
case (some[def](def_local(?d))) { ret gen_poststate(fcx, a, d); }
case (_) { ret false; }
case (some[def](def_local(?loc))) {
ret gen_poststate(fcx, a, loc);
}
case (_) { ret false; }
}
}
@ -420,9 +422,9 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool {
log("if:");
log_expr(*e);
log("new prestate:");
log_bitv(fcx.enclosing, pres);
log_bitv(fcx, pres);
log("new poststate:");
log_bitv(fcx.enclosing, expr_poststate(fcx.ccx, e));
log_bitv(fcx, expr_poststate(fcx.ccx, e));
ret changed;
}
@ -637,10 +639,9 @@ fn find_pre_post_state_stmt(&fn_ctxt fcx, &prestate pres, @stmt s) -> bool {
log_stmt(*s);
log("prestate = ");
log(bitv::to_str(stmt_ann.states.prestate));
log_bitv(fcx.enclosing, stmt_ann.states.prestate);
log_bitv(fcx, stmt_ann.states.prestate);
log("poststate =");
log_bitv(fcx.enclosing,
stmt_ann.states.poststate);
log_bitv(fcx, stmt_ann.states.poststate);
log("changed =");
log(changed);
@ -740,9 +741,9 @@ fn find_pre_post_state_block(&fn_ctxt fcx, &prestate pres0, &block b)
log("poststate = ");
log_states(block_states(fcx.ccx, b));
log("pres0:");
log_bitv(fcx.enclosing, pres0);
log_bitv(fcx, pres0);
log("post:");
log_bitv(fcx.enclosing, post);
log_bitv(fcx, post);
ret changed;
}

View file

@ -4,6 +4,8 @@ import std::option;
import std::option::some;
import std::option::none;
import front::ast::span;
// FIXME: Should visit patterns as well.
type ast_visitor =
rec(fn () -> bool keep_going,
@ -32,9 +34,9 @@ type ast_visitor =
fn (&@ast::expr e) visit_expr_post,
fn (&@ast::ty t) visit_ty_pre,
fn (&@ast::ty t) visit_ty_post,
fn (&ast::_fn f, &ast::ident name,
fn (&ast::_fn f, &span sp, &ast::ident name,
&ast::def_id d_id, &ast::ann a) visit_fn_pre,
fn (&ast::_fn f, &ast::ident name,
fn (&ast::_fn f, &span sp, &ast::ident name,
&ast::def_id d_id, &ast::ann a) visit_fn_post);
fn walk_crate(&ast_visitor v, &ast::crate c) {
@ -95,8 +97,8 @@ fn walk_item(&ast_visitor v, @ast::item i) {
walk_ty(v, t);
walk_expr(v, e);
}
case (ast::item_fn(?i, ?f, _, ?d, ?a)) {
walk_fn(v, f, i, d, a);
case (ast::item_fn(?nm, ?f, _, ?d, ?a)) {
walk_fn(v, f, i.span, nm, d, a);
}
case (ast::item_mod(_, ?m, _)) {
walk_mod(v, m);
@ -120,13 +122,14 @@ fn walk_item(&ast_visitor v, @ast::item i) {
}
for (@ast::method m in ob.methods) {
v.visit_method_pre(m);
walk_fn(v, m.node.meth, m.node.ident, m.node.id, m.node.ann);
walk_fn(v, m.node.meth, m.span,
m.node.ident, m.node.id, m.node.ann);
v.visit_method_post(m);
}
alt (ob.dtor) {
case (none[@ast::method]) {}
case (some[@ast::method](?m)) {
walk_fn(v, m.node.meth, m.node.ident, m.node.id,
walk_fn(v, m.node.meth, m.span, m.node.ident, m.node.id,
m.node.ann);
}
}
@ -232,13 +235,13 @@ fn walk_fn_decl(&ast_visitor v, &ast::fn_decl fd) {
walk_ty(v, fd.output);
}
fn walk_fn(&ast_visitor v, &ast::_fn f, &ast::ident i, &ast::def_id d,
&ast::ann a) {
fn walk_fn(&ast_visitor v, &ast::_fn f, &span sp, &ast::ident i,
&ast::def_id d, &ast::ann a) {
if (!v.keep_going()) { ret; }
v.visit_fn_pre(f, i, d, a);
v.visit_fn_pre(f, sp, i, d, a);
walk_fn_decl(v, f.decl);
walk_block(v, f.body);
v.visit_fn_post(f, i, d, a);
v.visit_fn_post(f, sp, i, d, a);
}
fn walk_block(&ast_visitor v, &ast::block b) {
@ -471,7 +474,7 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
// Methods
for (@ast::method m in anon_obj.methods) {
v.visit_method_pre(m);
walk_fn(v, m.node.meth, m.node.ident,
walk_fn(v, m.node.meth, m.span, m.node.ident,
m.node.id, m.node.ann);
v.visit_method_post(m);
@ -495,7 +498,8 @@ fn def_visit_arm(&ast::arm a) { }
fn def_visit_decl(&@ast::decl d) { }
fn def_visit_expr(&@ast::expr e) { }
fn def_visit_ty(&@ast::ty t) { }
fn def_visit_fn(&ast::_fn f, &ast::ident i, &ast::def_id d, &ast::ann a) { }
fn def_visit_fn(&ast::_fn f, &span sp, &ast::ident i, &ast::def_id d,
&ast::ann a) { }
fn default_visitor() -> ast_visitor {

View file

@ -0,0 +1,25 @@
// -*- rust -*-
// error-pattern: a \[./src/test/compile-fail/shadow.rs:11:8:11:20
fn foo(vec[int] c) {
let int a = 5;
let vec[int] b = [];
alt (none[int]) {
case (some[int](_)) {
for (int i in c) {
log a;
auto a = 17;
b += [a];
}
}
}
}
tag t[T] {
none;
some(T);
}
fn main() {
foo([]);
}