From 764e9c19690f55e61e5d0109c03023847ce6fd26 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 16 May 2011 17:40:29 -0700 Subject: [PATCH 01/10] Fix an error message that reversed the expected and actual number of arguments in a pattern --- src/comp/middle/typeck.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index c8229e6c84999..ba2b56b6a578b 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1685,9 +1685,9 @@ fn check_pat(&@stmt_ctxt scx, &@ast::pat pat) { if (arg_len != subpats_len) { // TODO: pluralize properly auto err_msg = "tag type " + last_id + " has " + - uint::to_str(subpats_len, 10u) + - " field(s), but this pattern has " + uint::to_str(arg_len, 10u) + + " field(s), but this pattern has " + + uint::to_str(subpats_len, 10u) + " field(s)"; scx.fcx.ccx.sess.span_err(pat.span, err_msg); From 6cfe082cdd7301f89838dfccf41b1843fb2e7fbe Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 16 May 2011 17:49:46 -0700 Subject: [PATCH 02/10] Beginning of Operation Eliminate Folds Started by rewriting collect_locals to use walk instead of fold --- src/comp/middle/tstate/collect_locals.rs | 79 +++++++++++++----------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/src/comp/middle/tstate/collect_locals.rs b/src/comp/middle/tstate/collect_locals.rs index 8ec5656cfe636..29f73a149c786 100644 --- a/src/comp/middle/tstate/collect_locals.rs +++ b/src/comp/middle/tstate/collect_locals.rs @@ -19,12 +19,12 @@ import front::ast::decl; import front::ast::decl_local; import front::ast::def_id; import front::ast::ident; + import middle::fold::span; import middle::fold::respan; -import middle::fold::new_identity_fold; -import middle::fold::fold_block; -import middle::fold::fold_fn; -import middle::fold::fold_crate; +import middle::walk::walk_crate; +import middle::walk::walk_fn; +import middle::walk::ast_visitor; import aux::fn_info; import aux::var_info; @@ -36,19 +36,17 @@ 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, &span sp, &@local loc) - -> @decl { +fn collect_local(&@vec[tup(ident, def_id)] vars, &@local loc) -> () { log("collect_local: pushing " + loc.ident); - vec::push[tup(ident, def_id)](*vars, tup(loc.ident, loc.id)); - ret @respan(sp, decl_local(loc)); + _vec::push[tup(ident, def_id)](*vars, tup(loc.ident, loc.id)); } fn find_locals(_fn f) -> @vec[tup(ident,def_id)] { auto res = @vec::alloc[tup(ident,def_id)](0u); - auto fld = new_identity_fold[@vec[tup(ident, def_id)]](); - fld = @rec(fold_decl_local = bind collect_local(_,_,_) with *fld); - auto ignore = fold_fn[@vec[tup(ident, def_id)]](res, fld, f); + auto visitor = walk::default_visitor(); + visitor = rec(visit_decl_pre=bind collect_local(res,_) with visitor); + walk_fn(visitor, f); ret res; } @@ -83,40 +81,47 @@ fn mk_fn_info(_fn f, def_id f_id, ident f_name) -> fn_info { ret res; } -/* extends mk_fn_info to a function item, side-effecting the map fi from - function IDs to fn_info maps */ -fn mk_fn_info_item_fn(&crate_ctxt ccx, &span sp, &ident i, &_fn f, - &vec[ty_param] ty_params, &def_id id, &ann a) -> @item { - auto f_inf = mk_fn_info(f, id, i); - ccx.fm.insert(id, f_inf); - // log_err("inserting: " + i); - ret @respan(sp, item_fn(i, f, ty_params, id, a)); -} - -/* extends mk_fn_info to an obj item, side-effecting the map fi from - function IDs to fn_info maps */ -fn mk_fn_info_item_obj(&crate_ctxt ccx, &span sp, &ident i, &_obj o, - &vec[ty_param] ty_params, - &obj_def_ids odid, &ann a) -> @item { - auto all_methods = vec::clone[@method](o.methods); - plus_option[@method](all_methods, o.dtor); - auto f_inf; - for (@method m in all_methods) { +/* extends mk_fn_info to an item, side-effecting the map fi from + function IDs to fn_info maps + only looks at function and object items. */ +fn mk_fn_info_item (&crate_ctxt ccx, &@item i) -> () { + alt (i.node) { + case (item_fn(?i,?f,?ty_params,?id,?a)) { + auto f_inf = mk_fn_info(f, id, i); + ccx.fm.insert(id, f_inf); + } + case (item_obj(?i,?o,?ty_params,?odid,?a)) { + auto all_methods = _vec::clone[@method](o.methods); + plus_option[@method](all_methods, o.dtor); + auto f_inf; + for (@method m in all_methods) { f_inf = mk_fn_info(m.node.meth, m.node.id, m.node.ident); ccx.fm.insert(m.node.id, f_inf); + } } - ret @respan(sp, item_obj(i, o, ty_params, odid, a)); + case (_) { ret; } + } } - /* initializes the global fn_info_map (mapping each function ID, including nested locally defined functions, onto a mapping from local variable name 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_item_post=bind mk_fn_info_item(ccx,_) + with vars_visitor); - auto fld = new_identity_fold[crate_ctxt](); - fld = @rec(fold_item_fn = bind mk_fn_info_item_fn(_,_,_,_,_,_,_), - fold_item_obj = bind mk_fn_info_item_obj(_,_,_,_,_,_,_) - with *fld); - fold_crate[crate_ctxt](ccx, fld, c); + walk_crate(vars_visitor, *c); } + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// + From 2a024e3ef9935c080dadc831a61b98efa4a44326 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:34:21 -0700 Subject: [PATCH 03/10] Remove dead file (typestate_check is now a bunch of modules under middle/tstate) --- src/comp/middle/typestate_check.rs | 2377 ---------------------------- 1 file changed, 2377 deletions(-) delete mode 100644 src/comp/middle/typestate_check.rs diff --git a/src/comp/middle/typestate_check.rs b/src/comp/middle/typestate_check.rs deleted file mode 100644 index a183ed3d1221a..0000000000000 --- a/src/comp/middle/typestate_check.rs +++ /dev/null @@ -1,2377 +0,0 @@ -import front::ast; -import front::ast::ann; -import front::ast::method; -import front::ast::ty; -import front::ast::mutability; -import front::ast::item; -import front::ast::block; -import front::ast::block_; -import front::ast::obj_field; -import front::ast::decl; -import front::ast::arm; -import front::ast::stmt; -import front::ast::stmt_; -import front::ast::stmt_decl; -import front::ast::stmt_expr; -import front::ast::stmt_crate_directive; -import front::ast::decl_local; -import front::ast::decl_item; -import front::ast::ident; -import front::ast::def_id; -import front::ast::ann; -import front::ast::field; -import front::ast::expr; -import front::ast::expr_call; -import front::ast::expr_vec; -import front::ast::expr_tup; -import front::ast::expr_path; -import front::ast::expr_field; -import front::ast::expr_index; -import front::ast::expr_log; -import front::ast::expr_block; -import front::ast::expr_rec; -import front::ast::expr_if; -import front::ast::expr_binary; -import front::ast::expr_unary; -import front::ast::expr_assign; -import front::ast::expr_assign_op; -import front::ast::expr_while; -import front::ast::expr_do_while; -import front::ast::expr_alt; -import front::ast::expr_lit; -import front::ast::expr_ret; -import front::ast::expr_self_method; -import front::ast::expr_bind; -import front::ast::expr_spawn; -import front::ast::expr_ext; -import front::ast::expr_fail; -import front::ast::expr_break; -import front::ast::expr_cont; -import front::ast::expr_send; -import front::ast::expr_recv; -import front::ast::expr_put; -import front::ast::expr_port; -import front::ast::expr_chan; -import front::ast::expr_be; -import front::ast::expr_check; -import front::ast::expr_assert; -import front::ast::expr_cast; -import front::ast::expr_for; -import front::ast::expr_for_each; -import front::ast::path; -import front::ast::elt; -import front::ast::crate_directive; -import front::ast::fn_decl; -import front::ast::_obj; -import front::ast::native_mod; -import front::ast::variant; -import front::ast::ty_param; -import front::ast::ty; -import front::ast::proto; -import front::ast::pat; -import front::ast::binop; -import front::ast::unop; -import front::ast::def; -import front::ast::lit; -import front::ast::init_op; -import front::ast::initializer; -import front::ast::local; -import front::ast::_fn; -import front::ast::_obj; -import front::ast::_mod; -import front::ast::crate; -import front::ast::item_fn; -import front::ast::item_obj; -import front::ast::def_local; - -import middle::fold; -import middle::fold::respan; -import driver::session; -import util::common; -import util::common::span; -import util::common::spanned; -import util::common::new_str_hash; -import util::common::new_def_hash; -import util::common::uistr; -import util::common::elt_exprs; -import util::common::field_exprs; -import util::common::log_expr; -import util::common::log_expr_err; -import util::common::log_stmt; -import util::common::log_block; -import util::common::log_stmt_err; -import util::common::log_fn_err; -import util::common::log_fn; -import util::common::log_block_err; -import util::common::has_nonlocal_exits; -import util::common::decl_lhs; -import util::typestate_ann; -import util::typestate_ann::ts_ann; -import util::typestate_ann::empty_pre_post; -import util::typestate_ann::empty_poststate; -import util::typestate_ann::true_precond; -import util::typestate_ann::true_postcond; -import util::typestate_ann::false_postcond; -import util::typestate_ann::postcond; -import util::typestate_ann::precond; -import util::typestate_ann::poststate; -import util::typestate_ann::prestate; -import util::typestate_ann::pre_and_post; -import util::typestate_ann::get_pre; -import util::typestate_ann::get_post; -import util::typestate_ann::ann_precond; -import util::typestate_ann::ann_prestate; -import util::typestate_ann::set_precondition; -import util::typestate_ann::set_postcondition; -import util::typestate_ann::set_prestate; -import util::typestate_ann::set_poststate; -import util::typestate_ann::set_in_postcond; -import util::typestate_ann::set_in_poststate; -import util::typestate_ann::implies; -import util::typestate_ann::pre_and_post_state; -import util::typestate_ann::empty_states; -import util::typestate_ann::empty_prestate; -import util::typestate_ann::empty_ann; -import util::typestate_ann::extend_prestate; -import util::typestate_ann::extend_poststate; -import util::typestate_ann::relax_prestate; -import util::typestate_ann::intersect; -import util::typestate_ann::pp_clone; -import util::typestate_ann::clone; - -import middle::ty; -import middle::ty::ann_to_type; -import middle::ty::arg; -import middle::ty::expr_ann; -import middle::ty::ty_to_str; - -import pretty::pprust::print_block; -import pretty::pprust::print_expr; -import pretty::pprust::print_decl; -import pretty::pp::mkstate; -import std::io::stdout; -import std::io::str_writer; -import std::io::string_writer; -import std::vec::map; -import std::vec; -import std::vec::len; -import std::vec::pop; -import std::vec::push; -import std::vec::slice; -import std::vec::unzip; -import std::vec::plus_option; -import std::vec::cat_options; -import std::option; -import std::option::t; -import std::option::some; -import std::option::none; -import std::option::from_maybe; -import std::option::maybe; -import std::option::is_none; -import std::option::get; -import std::map::hashmap; -import std::list; -import std::list::list; -import std::list::cons; -import std::list::nil; -import std::list::foldl; -import std::list::find; -import std::uint; -import std::bitv; -import std::util::fst; -import std::util::snd; - -import util::typestate_ann; -import util::typestate_ann::difference; -import util::typestate_ann::union; -import util::typestate_ann::pps_len; -import util::typestate_ann::require_and_preserve; - -import resolve::def_map; - -/**** debugging junk ****/ - -fn bitv_to_str(fn_info enclosing, bitv::t v) -> str { - auto s = ""; - - for each (@tup(def_id, tup(uint, ident)) p in enclosing.items()) { - if (bitv::get(v, p._1._0)) { - s += " " + p._1._1 + " "; - } - } - ret s; -} - -fn log_bitv(fn_info enclosing, bitv::t v) { - log(bitv_to_str(enclosing, v)); -} - -fn log_bitv_err(fn_info enclosing, bitv::t v) { - log_err(bitv_to_str(enclosing, v)); -} - -fn tos (vec[uint] v) -> str { - auto res = ""; - for (uint i in v) { - if (i == 0u) { - res += "0"; - } - else { - res += "1"; - } - } - ret res; -} - -fn log_cond(vec[uint] v) -> () { - log(tos(v)); -} -fn log_cond_err(vec[uint] v) -> () { - log_err(tos(v)); -} - -fn log_pp(&pre_and_post pp) -> () { - auto p1 = bitv::to_vec(pp.precondition); - auto p2 = bitv::to_vec(pp.postcondition); - log("pre:"); - log_cond(p1); - log("post:"); - log_cond(p2); -} - -fn log_pp_err(&pre_and_post pp) -> () { - auto p1 = bitv::to_vec(pp.precondition); - auto p2 = bitv::to_vec(pp.postcondition); - log_err("pre:"); - log_cond_err(p1); - log_err("post:"); - log_cond_err(p2); -} - -fn log_states(&pre_and_post_state pp) -> () { - auto p1 = bitv::to_vec(pp.prestate); - auto p2 = bitv::to_vec(pp.poststate); - log("prestate:"); - log_cond(p1); - log("poststate:"); - log_cond(p2); -} - -fn log_states_err(&pre_and_post_state pp) -> () { - auto p1 = bitv::to_vec(pp.prestate); - auto p2 = bitv::to_vec(pp.poststate); - log_err("prestate:"); - log_cond_err(p1); - log_err("poststate:"); - log_cond_err(p2); -} - -fn print_ident(&ident i) -> () { - log(" " + i + " "); -} - -fn print_idents(vec[ident] idents) -> () { - if(len[ident](idents) == 0u) { - ret; - } - else { - log("an ident: " + pop[ident](idents)); - print_idents(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); -type fn_info = std::map::hashmap[def_id, var_info]; -/* mapping from function name to fn_info map */ -type fn_info_map = std::map::hashmap[def_id, fn_info]; - -fn bit_num(def_id v, fn_info m) -> uint { - assert (m.contains_key(v)); - ret m.get(v)._0; -} -fn get_fn_info(fn_info_map fm, def_id did) -> fn_info { - assert (fm.contains_key(did)); - ret fm.get(did); -} - -fn var_is_local(def_id v, fn_info m) -> bool { - ret (m.contains_key(v)); -} - -fn num_locals(fn_info m) -> uint { - ret m.size(); -} - -fn collect_local(&@vec[tup(ident, def_id)] vars, &span sp, &@ast::local loc) - -> @decl { - log("collect_local: pushing " + loc.ident); - vec::push[tup(ident, def_id)](*vars, tup(loc.ident, loc.id)); - ret @respan(sp, decl_local(loc)); -} - -fn find_locals(_fn f) -> @vec[tup(ident,def_id)] { - auto res = @vec::alloc[tup(ident,def_id)](0u); - - auto fld = fold::new_identity_fold[@vec[tup(ident, def_id)]](); - fld = @rec(fold_decl_local = bind collect_local(_,_,_) with *fld); - auto ignore = fold::fold_fn[@vec[tup(ident, def_id)]](res, fld, f); - - ret res; -} - -fn add_var(def_id v, ident nm, uint next, fn_info tbl) -> uint { - log(nm + " |-> " + util::common::uistr(next)); - tbl.insert(v, tup(next,nm)); - 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(_fn f) -> fn_info { - auto res = new_def_hash[var_info](); - let uint next = 0u; - let vec[ast::arg] f_args = f.decl.inputs; - - /* ignore args, which we know are initialized; - just collect locally declared vars */ - - let @vec[tup(ident,def_id)] locals = find_locals(f); - log(uistr(vec::len[tup(ident, def_id)](*locals)) + " locals"); - for (tup(ident,def_id) p in *locals) { - next = add_var(p._1, p._0, next, res); - } - - ret res; -} - -/* extends mk_fn_info to a function item, side-effecting the map fi from - function IDs to fn_info maps */ -fn mk_fn_info_item_fn(&fn_info_map fi, &span sp, &ident i, &ast::_fn f, - &vec[ast::ty_param] ty_params, &def_id id, &ann a) -> @item { - fi.insert(id, mk_fn_info(f)); - log(i + " has " + uistr(num_locals(mk_fn_info(f))) + " local vars"); - ret @respan(sp, item_fn(i, f, ty_params, id, a)); -} - -/* extends mk_fn_info to an obj item, side-effecting the map fi from - function IDs to fn_info maps */ -fn mk_fn_info_item_obj(&fn_info_map fi, &span sp, &ident i, &ast::_obj o, - &vec[ast::ty_param] ty_params, - &ast::obj_def_ids odid, &ann a) -> @item { - auto all_methods = vec::clone[@method](o.methods); - plus_option[@method](all_methods, o.dtor); - for (@method m in all_methods) { - fi.insert(m.node.id, mk_fn_info(m.node.meth)); - log(m.node.ident + " has " + - uistr(num_locals(mk_fn_info(m.node.meth))) + " local vars"); - } - ret @respan(sp, item_obj(i, o, ty_params, odid, a)); -} - -/* initializes the global fn_info_map (mapping each function ID, including - nested locally defined functions, onto a mapping from local variable name - to bit number) */ -fn mk_f_to_fn_info(@ast::crate c) -> fn_info_map { - auto res = new_def_hash[fn_info](); - - auto fld = fold::new_identity_fold[fn_info_map](); - fld = @rec(fold_item_fn = bind mk_fn_info_item_fn(_,_,_,_,_,_,_), - fold_item_obj = bind mk_fn_info_item_obj(_,_,_,_,_,_,_) - with *fld); - fold::fold_crate[fn_info_map](res, fld, c); - - ret res; -} -/**** Helpers ****/ -fn ann_to_ts_ann(ann a, uint nv) -> ts_ann { - alt (a.ts) { - /* Kind of inconsistent. empty_ann()s everywhere - or an option of a ts_ann? */ - case (none[@ts_ann]) { ret empty_ann(nv); } - case (some[@ts_ann](?t)) { ret *t; } - } -} - -fn ann_to_ts_ann_fail(ann a) -> option::t[@ts_ann] { ret a.ts; } - -fn ann_to_ts_ann_fail_more(ann a) -> @ts_ann { - assert (! is_none[@ts_ann](a.ts)); - ret get[@ts_ann](a.ts); -} - -fn ann_to_poststate(ann a) -> poststate { - ret (ann_to_ts_ann_fail_more(a)).states.poststate; -} - -fn stmt_to_ann(&stmt s) -> option::t[@ts_ann] { - alt (s.node) { - case (stmt_decl(_,?a)) { - ret ann_to_ts_ann_fail(a); - } - case (stmt_expr(_,?a)) { - ret ann_to_ts_ann_fail(a); - } - case (stmt_crate_directive(_)) { - ret none[@ts_ann]; - } - } -} - -/* fails if e has no annotation */ -fn expr_states(@expr e) -> pre_and_post_state { - alt (a.ts) { - case (none[@ts_ann]) { - log_err "expr_pp: the impossible happened (no pre/post)"; - fail; - } - case (some[@ts_ann](?p)) { ret p.states; } - } -} - -/* fails if e has no annotation */ -fn expr_pp(@expr e) -> pre_and_post { - alt (expr_ann(e).ts) { - case (none[@ts_ann]) { - log_err "expr_pp: the impossible happened (no pre/post)"; - fail; - } - case (some[@ts_ann](?p)) { ret p.conditions; } - } -} - -fn stmt_pp(&stmt s) -> pre_and_post { - alt (stmt_to_ann(s)) { - case (none[@ts_ann]) { - log "stmt_pp: the impossible happened (no annotation)"; - fail; - } - case (some[@ts_ann](?p)) { - ret p.conditions; - } - } -} - -/* fails if b has no annotation */ -/* FIXME: factor out code in the following two functions (block_ts_ann) */ -fn block_pp(&block b) -> pre_and_post { - alt (b.node.a.ts) { - case (none[@ts_ann]) { - log_err "block_pp: the impossible happened (no ty)"; - fail; - } - case (some[@ts_ann](?ts)) { ret ts.conditions; } - } -} - -fn block_states(&block b) -> pre_and_post_state { - alt (b.node.a.ts) { - case (none[@ts_ann]) { - log_err "block_states: the impossible happened (no ty)"; - fail; - } - case (some[@ts_ann](?ts)) { ret ts.states; } - } -} - -fn stmt_states(&stmt s, uint nv) -> pre_and_post_state { - alt (stmt_to_ann(s)) { - case (none[@ts_ann]) { - ret empty_states(nv); - } - case (some[@ts_ann](?a)) { - ret a.states; - } - } -} - - -fn expr_precond(@expr e) -> precond { - ret (expr_pp(e)).precondition; -} - -fn expr_postcond(@expr e) -> postcond { - ret (expr_pp(e)).postcondition; -} - -fn expr_prestate(@expr e) -> prestate { - ret (expr_states(e)).prestate; -} - -fn expr_poststate(@expr e) -> poststate { - ret (expr_states(e)).poststate; -} - -/* -fn stmt_precond(&stmt s) -> precond { - ret (stmt_pp(s)).precondition; -} - -fn stmt_postcond(&stmt s) -> postcond { - ret (stmt_pp(s)).postcondition; -} -*/ - -fn states_to_poststate(&pre_and_post_state ss) -> poststate { - ret ss.poststate; -} - -/* -fn stmt_prestate(&stmt s) -> prestate { - ret (stmt_states(s)).prestate; -} -*/ -fn stmt_poststate(&stmt s, uint nv) -> poststate { - ret (stmt_states(s, nv)).poststate; -} - -fn block_postcond(&block b) -> postcond { - ret (block_pp(b)).postcondition; -} - -fn block_poststate(&block b) -> poststate { - ret (block_states(b)).poststate; -} - -/* returns a new annotation where the pre_and_post is p */ -fn with_pp(ann a, pre_and_post p) -> ann { - ret rec(id=ann.id, ty=ann.ty, tps=ann.tps, - ts=some[@ts_ann](@rec(conditions=p, - states=empty_states(pps_len(p))))); -} - -// Given a list of pres and posts for exprs e0 ... en, -// 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 { - let uint sz = len[pre_and_post](pps); - let uint num_vars = num_locals(enclosing); - - if (sz >= 1u) { - auto first = pps.(0); - assert (pps_len(first) == num_vars); - let precond rest = seq_preconds(enclosing, - slice[pre_and_post](pps, 1u, sz)); - difference(rest, first.postcondition); - auto res = clone(first.precondition); - union(res, rest); - - log("seq_preconds:"); - log("first.postcondition ="); - log_bitv(enclosing, first.postcondition); - log("rest ="); - log_bitv(enclosing, rest); - log("returning"); - log_bitv(enclosing, res); - - ret res; - } - else { - ret true_precond(num_vars); - } -} - -/* works on either postconds or preconds - should probably rethink the whole type synonym situation */ -fn union_postconds_go(&postcond first, &vec[postcond] rest) -> postcond { - auto sz = vec::len[postcond](rest); - - if (sz > 0u) { - auto other = rest.(0); - union(first, other); - union_postconds_go(first, slice[postcond](rest, 1u, len[postcond](rest))); - } - - ret first; -} - -fn union_postconds(uint nv, &vec[postcond] pcs) -> postcond { - if (len[postcond](pcs) > 0u) { - ret union_postconds_go(bitv::clone(pcs.(0)), pcs); - } - else { - ret empty_prestate(nv); - } -} - -/* Gee, maybe we could use foldl or something */ -fn intersect_postconds_go(&postcond first, &vec[postcond] rest) -> postcond { - auto sz = vec::len[postcond](rest); - - if (sz > 0u) { - auto other = rest.(0); - intersect(first, other); - intersect_postconds_go(first, slice[postcond](rest, 1u, - len[postcond](rest))); - } - - ret first; -} - -fn intersect_postconds(&vec[postcond] pcs) -> postcond { - assert (len[postcond](pcs) > 0u); - - ret intersect_postconds_go(bitv::clone(pcs.(0)), pcs); -} - -/******* AST-traversing code ********/ - -fn find_pre_post_mod(&_mod m) -> _mod { - log("implement find_pre_post_mod!"); - fail; -} - -fn find_pre_post_state_mod(&_mod m) -> bool { - log("implement find_pre_post_state_mod!"); - fail; -} - -fn find_pre_post_native_mod(&native_mod m) -> native_mod { - log("implement find_pre_post_native_mod"); - fail; -} - -fn find_pre_post_state_native_mod(&native_mod m) -> bool { - log("implement find_pre_post_state_native_mod!"); - fail; -} - -fn find_pre_post_obj(&def_map dm, &fn_info_map fm, _obj o) -> () { - fn do_a_method(def_map dm, fn_info_map fm, &@method m) -> () { - assert (fm.contains_key(m.node.id)); - find_pre_post_fn(dm, fm, fm.get(m.node.id), m.node.meth); - } - auto f = bind do_a_method(dm, fm, _); - vec::map[@method, ()](f, o.methods); - option::map[@method, ()](f, o.dtor); -} - -fn find_pre_post_state_obj(&def_map dm, &fn_info_map fm, _obj o) -> bool { - fn do_a_method(def_map dm, fn_info_map fm, &@method m) -> bool { - assert (fm.contains_key(m.node.id)); - ret find_pre_post_state_fn(dm, fm, fm.get(m.node.id), m.node.meth); - } - auto f = bind do_a_method(dm, fm, _); - auto flags = vec::map[@method, bool](f, o.methods); - auto changed = vec::or(flags); - changed = changed || maybe[@method, bool](false, f, o.dtor); - ret changed; -} - -fn find_pre_post_item(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &item i) -> () { - alt (i.node) { - case (ast::item_const(?id, ?t, ?e, ?di, ?a)) { - find_pre_post_expr(dm, fm, enclosing, e); - } - case (ast::item_fn(?id, ?f, ?ps, ?di, ?a)) { - assert (fm.contains_key(di)); - find_pre_post_fn(dm, fm, fm.get(di), f); - } - case (ast::item_mod(?id, ?m, ?di)) { - find_pre_post_mod(m); - } - case (ast::item_native_mod(?id, ?nm, ?di)) { - find_pre_post_native_mod(nm); - } - case (ast::item_ty(_,_,_,_,_)) { - ret; - } - case (ast::item_tag(_,_,_,_,_)) { - ret; - } - case (ast::item_obj(?id, ?o, ?ps, ?di, ?a)) { - find_pre_post_obj(dm, fm, o); - } - } -} - -/* Finds the pre and postcondition for each expr in ; - sets the precondition in a to be the result of combining - the preconditions for , and the postcondition in a to - be the union of all postconditions for */ -fn find_pre_post_exprs(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &vec[@expr] args, ann a) { - auto nv = num_locals(enclosing); - - fn do_one(def_map dm, fn_info_map fm, fn_info enclosing, - &@expr e) -> () { - find_pre_post_expr(dm, fm, enclosing, e); - } - auto f = bind do_one(dm, fm, enclosing, _); - - vec::map[@expr, ()](f, args); - - fn get_pp(&@expr e) -> pre_and_post { - ret expr_pp(e); - } - auto g = get_pp; - auto pps = vec::map[@expr, pre_and_post](g, args); - auto h = get_post; - - set_pre_and_post(a, - rec(precondition=seq_preconds(enclosing, pps), - postcondition=union_postconds - (nv, (vec::map[pre_and_post, postcond](h, pps))))); -} - -fn find_pre_post_loop(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &@decl d, &@expr index, &block body, &ann a) -> () { - find_pre_post_expr(dm, fm, enclosing, index); - find_pre_post_block(dm, fm, enclosing, body); - auto loop_precond = declare_var(enclosing, decl_lhs(d), - seq_preconds(enclosing, [expr_pp(index), - block_pp(body)])); - auto loop_postcond = intersect_postconds - ([expr_postcond(index), block_postcond(body)]); - set_pre_and_post(a, rec(precondition=loop_precond, - postcondition=loop_postcond)); -} - -/* Fills in annotations as a side effect. Does not rebuild the expr */ -fn find_pre_post_expr(&def_map dm, &fn_info_map fm, &fn_info enclosing, - @expr e) -> () { - auto num_local_vars = num_locals(enclosing); - - log("find_pre_post_expr (num_locals =" + - uistr(num_local_vars) + "):"); - log_expr(*e); - - alt (e.node) { - case (expr_call(?operator, ?operands, ?a)) { - auto args = vec::clone[@expr](operands); - vec::push[@expr](args, operator); - find_pre_post_exprs(dm, fm, enclosing, args, a); - } - case (expr_spawn(_, _, ?operator, ?operands, ?a)) { - auto args = vec::clone[@expr](operands); - vec::push[@expr](args, operator); - find_pre_post_exprs(dm, fm, enclosing, args, a); - } - case (expr_vec(?args, _, ?a)) { - find_pre_post_exprs(dm, fm, enclosing, args, a); - } - case (expr_tup(?elts, ?a)) { - find_pre_post_exprs(dm, fm, enclosing, elt_exprs(elts), a); - } - case (expr_path(?p, ?a)) { - auto res = empty_pre_post(num_local_vars); - - alt (dm.get(a.id)) { - case (def_local(?d_id)) { - auto i = bit_num(d_id, enclosing); - require_and_preserve(i, res); - } - case (_) { /* nothing to check */ } - } - - // Otherwise, variable is global, so it must be initialized - set_pre_and_post(a, res); - } - case (expr_self_method(?v, ?a)) { - /* v is a method of the enclosing obj, so it must be - initialized, right? */ - set_pre_and_post(a, empty_pre_post(num_local_vars)); - } - case(expr_log(_, ?arg, ?a)) { - find_pre_post_expr(dm, fm, enclosing, arg); - set_pre_and_post(a, expr_pp(arg)); - } - case (expr_chan(?arg, ?a)) { - find_pre_post_expr(dm, fm, enclosing, arg); - set_pre_and_post(a, expr_pp(arg)); - } - case(expr_put(?opt, ?a)) { - alt (opt) { - case (some[@expr](?arg)) { - find_pre_post_expr(dm, fm, enclosing, arg); - set_pre_and_post(a, expr_pp(arg)); - } - case (none[@expr]) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); - } - } - } - case (expr_block(?b, ?a)) { - find_pre_post_block(dm, fm, enclosing, b); - set_pre_and_post(a, block_pp(b)); - } - case (expr_rec(?fields,?maybe_base,?a)) { - auto es = field_exprs(fields); - vec::plus_option[@expr](es, maybe_base); - find_pre_post_exprs(dm, fm, enclosing, es, a); - } - case (expr_assign(?lhs, ?rhs, ?a)) { - alt (lhs.node) { - case (expr_path(?p, ?a_lhs)) { - alt (dm.get(a_lhs.id))) { - case (def_local(?d_id)) { - find_pre_post_expr(dm, fm, enclosing, rhs); - set_pre_and_post(a, expr_pp(rhs)); - log("gen:"); - log_expr(*e); - gen(enclosing, a, d_id); - ret; - } - case (_) {} - } - } - case (_) {} - } - // doesn't check that lhs is an lval, but - // that's probably ok - find_pre_post_exprs(dm, fm, enclosing, [lhs, rhs], a); - } - case (expr_recv(?lhs, ?rhs, ?a)) { - alt (lhs.node) { - case (expr_path(?p, ?a_lhs)) { - alt (dm.get(a_lhs.id)) { - case (def_local(?d_id)) { - find_pre_post_expr(dm, fm, enclosing, rhs); - set_pre_and_post(a, expr_pp(rhs)); - log("gen:"); - log_expr(*e); - gen(enclosing, a, d_id); - ret; - } - case (_) {} - } - } - case (_) {} - } - // doesn't check that lhs is an lval, but - // that's probably ok - find_pre_post_exprs(dm, fm, enclosing, [lhs, rhs], a); - } - case (expr_assign_op(_, ?lhs, ?rhs, ?a)) { - /* Different from expr_assign in that the lhs *must* - already be initialized */ - find_pre_post_exprs(dm, fm, enclosing, [lhs, rhs], a); - } - case (expr_lit(_,?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); - } - case (expr_ret(?maybe_val, ?a)) { - alt (maybe_val) { - case (none[@expr]) { - set_pre_and_post(a, - rec(precondition=true_precond(num_local_vars), - postcondition=false_postcond(num_local_vars))); - } - case (some[@expr](?ret_val)) { - find_pre_post_expr(dm, fm, enclosing, ret_val); - let pre_and_post pp = - rec(precondition=expr_precond(ret_val), - postcondition=false_postcond(num_local_vars)); - set_pre_and_post(a, pp); - } - } - } - case (expr_be(?e, ?a)) { - find_pre_post_expr(dm, fm, enclosing, e); - set_pre_and_post(a, rec(precondition=expr_prestate(e), - postcondition=false_postcond(num_local_vars))); - } - case (expr_if(?antec, ?conseq, ?maybe_alt, ?a)) { - find_pre_post_expr(dm, fm, enclosing, antec); - find_pre_post_block(dm, fm, enclosing, conseq); - alt (maybe_alt) { - case (none[@expr]) { - auto precond_res = seq_preconds(enclosing, - [expr_pp(antec), - block_pp(conseq)]); - set_pre_and_post(a, rec(precondition=precond_res, - postcondition= - expr_poststate(antec))); - } - case (some[@expr](?altern)) { - find_pre_post_expr(dm, fm, enclosing, altern); - auto precond_true_case = - seq_preconds(enclosing, - [expr_pp(antec), block_pp(conseq)]); - auto postcond_true_case = union_postconds - (num_local_vars, - [expr_postcond(antec), block_postcond(conseq)]); - auto precond_false_case = seq_preconds - (enclosing, - [expr_pp(antec), expr_pp(altern)]); - auto postcond_false_case = union_postconds - (num_local_vars, - [expr_postcond(antec), expr_postcond(altern)]); - auto precond_res = union_postconds - (num_local_vars, - [precond_true_case, precond_false_case]); - auto postcond_res = intersect_postconds - ([postcond_true_case, postcond_false_case]); - set_pre_and_post(a, rec(precondition=precond_res, - postcondition=postcond_res)); - } - } - } - case (expr_binary(?bop,?l,?r,?a)) { - /* *unless* bop is lazy (e.g. and, or)? - FIXME */ - find_pre_post_exprs(dm, fm, enclosing, [l, r], a); - } - case (expr_send(?l, ?r, ?a)) { - find_pre_post_exprs(dm, fm, enclosing, [l, r], a); - } - case (expr_unary(_,?operand,?a)) { - find_pre_post_expr(dm, fm, enclosing, operand); - set_pre_and_post(a, expr_pp(operand)); - } - case (expr_cast(?operand, _, ?a)) { - find_pre_post_expr(dm, fm, enclosing, operand); - set_pre_and_post(a, expr_pp(operand)); - } - case (expr_while(?test, ?body, ?a)) { - find_pre_post_expr(dm, fm, enclosing, test); - find_pre_post_block(dm, fm, enclosing, body); - set_pre_and_post(a, - rec(precondition= - seq_preconds(enclosing, - [expr_pp(test), - block_pp(body)]), - postcondition= - intersect_postconds([expr_postcond(test), - block_postcond(body)]))); - } - case (expr_do_while(?body, ?test, ?a)) { - find_pre_post_block(dm, fm, enclosing, body); - find_pre_post_expr(dm, fm, enclosing, test); - - auto loop_postcond = union_postconds(num_local_vars, - [block_postcond(body), expr_postcond(test)]); - /* conservative approximination: if the body - could break or cont, the test may never be executed */ - if (has_nonlocal_exits(body)) { - loop_postcond = empty_poststate(num_local_vars); - } - - set_pre_and_post(a, - rec(precondition=seq_preconds(enclosing, - [block_pp(body), - expr_pp(test)]), - postcondition=loop_postcond)); - } - case (expr_for(?d, ?index, ?body, ?a)) { - find_pre_post_loop(dm, fm, enclosing, d, index, body, a); - } - case (expr_for_each(?d, ?index, ?body, ?a)) { - find_pre_post_loop(dm, fm, enclosing, d, index, body, a); - } - case (expr_index(?e, ?sub, ?a)) { - find_pre_post_exprs(dm, fm, enclosing, [e, sub], a); - } - case (expr_alt(?e, ?alts, ?a)) { - find_pre_post_expr(dm, fm, enclosing, e); - fn do_an_alt(def_map dm, fn_info_map fm, fn_info enc, &arm an_alt) - -> pre_and_post { - find_pre_post_block(dm, fm, enc, an_alt.block); - ret block_pp(an_alt.block); - } - auto f = bind do_an_alt(dm, fm, enclosing, _); - 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, - &pre_and_post next) -> pre_and_post { - union(pp.precondition, seq_preconds(enclosing, - [antec, next])); - intersect(pp.postcondition, next.postcondition); - ret pp; - } - auto antec_pp = pp_clone(expr_pp(e)); - auto e_pp = rec(precondition=empty_prestate(num_local_vars), - postcondition=false_postcond(num_local_vars)); - auto g = bind combine_pp(antec_pp, enclosing, _, _); - - auto alts_overall_pp = vec::foldl[pre_and_post, pre_and_post] - (g, e_pp, alt_pps); - - set_pre_and_post(a, alts_overall_pp); - } - case (expr_field(?operator, _, ?a)) { - find_pre_post_expr(dm, fm, enclosing, operator); - set_pre_and_post(a, expr_pp(operator)); - } - case (expr_fail(?a)) { - set_pre_and_post(a, - /* if execution continues after fail, - then everything is true! */ - rec(precondition=empty_prestate(num_local_vars), - postcondition=false_postcond(num_local_vars))); - } - case (expr_assert(?p, ?a)) { - find_pre_post_expr(dm, fm, enclosing, p); - set_pre_and_post(a, expr_pp(p)); - } - case (expr_check(?p, ?a)) { - /* will need to change when we support arbitrary predicates... */ - find_pre_post_expr(dm, fm, enclosing, p); - set_pre_and_post(a, expr_pp(p)); - } - case(expr_bind(?operator, ?maybe_args, ?a)) { - auto args = vec::cat_options[@expr](maybe_args); - vec::push[@expr](args, operator); /* ??? order of eval? */ - find_pre_post_exprs(dm, fm, enclosing, args, a); - } - case (expr_break(?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); - } - case (expr_cont(?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); - } - case (expr_port(?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); - } - case (expr_ext(_, _, _, ?expanded, ?a)) { - find_pre_post_expr(dm, fm, enclosing, expanded); - set_pre_and_post(a, expr_pp(expanded)); - } - } -} - -fn gen(&fn_info enclosing, &ann a, def_id id) -> bool { - assert (enclosing.contains_key(id)); - let uint i = (enclosing.get(id))._0; - ret set_in_postcond(i, (ann_to_ts_ann_fail_more(a)).conditions); -} - -fn declare_var(&fn_info enclosing, def_id id, prestate pre) - -> prestate { - assert (enclosing.contains_key(id)); - let uint i = (enclosing.get(id))._0; - auto res = clone(pre); - relax_prestate(i, res); - ret res; -} - -fn gen_poststate(&fn_info enclosing, &ann a, def_id id) -> bool { - assert (enclosing.contains_key(id)); - let uint i = (enclosing.get(id))._0; - - ret set_in_poststate(i, (ann_to_ts_ann_fail_more(a)).states); -} - -fn find_pre_post_stmt(&def_map dm, fn_info_map fm, &fn_info enclosing, - &ast::stmt s) -> () { - log("stmt ="); - log_stmt(s); - - auto num_local_vars = num_locals(enclosing); - alt(s.node) { - case(ast::stmt_decl(?adecl, ?a)) { - alt(adecl.node) { - case(ast::decl_local(?alocal)) { - alt(alocal.init) { - case(some[ast::initializer](?an_init)) { - find_pre_post_expr(dm, fm, enclosing, an_init.expr); - auto rhs_pp = expr_pp(an_init.expr); - set_pre_and_post(alocal.ann, rhs_pp); - - /* Inherit ann from initializer, and add var being - initialized to the postcondition */ - set_pre_and_post(a, rhs_pp); - /* log("gen (decl):"); - log_stmt(s); */ - gen(enclosing, a, alocal.id); - /* log_err("for stmt"); - log_stmt(s); - log_err("pp = "); - log_pp(stmt_pp(s)); */ - } - case(none[ast::initializer]) { - auto pp = empty_pre_post(num_local_vars); - set_pre_and_post(alocal.ann, pp); - set_pre_and_post(a, pp); - } - } - } - case(decl_item(?anitem)) { - auto pp = empty_pre_post(num_local_vars); - set_pre_and_post(a, pp); - find_pre_post_item(dm, fm, enclosing, *anitem); - } - } - } - case(stmt_expr(?e,?a)) { - find_pre_post_expr(dm, fm, enclosing, e); - set_pre_and_post(a, expr_pp(e)); - } - } -} - -fn find_pre_post_block(&def_map dm, &fn_info_map fm, &fn_info enclosing, - block b) -> () { - /* Want to say that if there is a break or cont in this - block, then that invalidates the poststate upheld by - any of the stmts after it. - Given that the typechecker has run, we know any break will be in - a block that forms a loop body. So that's ok. There'll never be an - expr_break outside a loop body, therefore, no expr_break outside a block. - */ - - /* Conservative approximation for now: This says that if a block contains - *any* breaks or conts, then its postcondition doesn't promise anything. - This will mean that: - x = 0; - break; - - won't have a postcondition that says x is initialized, but that's ok. - */ - auto nv = num_locals(enclosing); - - fn do_one_(def_map dm, fn_info_map fm, fn_info i, &@stmt s) -> () { - find_pre_post_stmt(dm, fm, i, *s); - log("pre_post for stmt:"); - log_stmt(*s); - log("is:"); - log_pp(stmt_pp(*s)); - } - auto do_one = bind do_one_(dm, fm, enclosing, _); - - vec::map[@stmt, ()](do_one, b.node.stmts); - fn do_inner_(def_map dm, fn_info_map fm, fn_info i, &@expr e) -> () { - find_pre_post_expr(dm, fm, i, e); - } - auto do_inner = bind do_inner_(dm, fm, enclosing, _); - option::map[@expr, ()](do_inner, b.node.expr); - - let vec[pre_and_post] pps = []; - - fn get_pp_stmt(&@stmt s) -> pre_and_post { - ret stmt_pp(*s); - } - auto f = get_pp_stmt; - pps += vec::map[@stmt, pre_and_post](f, b.node.stmts); - fn get_pp_expr(&@expr e) -> pre_and_post { - ret expr_pp(e); - } - auto g = get_pp_expr; - plus_option[pre_and_post](pps, - option::map[@expr, pre_and_post](g, b.node.expr)); - - auto block_precond = seq_preconds(enclosing, 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 - vector is non-empty. */ - vec::push[postcond](postconds, block_precond); - auto block_postcond = empty_poststate(nv); - /* conservative approximation */ - if (! has_nonlocal_exits(b)) { - block_postcond = union_postconds(nv, postconds); - } - - set_pre_and_post(b.node.a, rec(precondition=block_precond, - postcondition=block_postcond)); -} - -fn find_pre_post_fn(&def_map dm, &fn_info_map fm, &fn_info fi, &_fn f) -> () { - find_pre_post_block(dm, fm, fi, f.body); -} - -fn check_item_fn(&def_map dm, &fn_info_map fm, &span sp, &ident i, - &ast::_fn f, &vec[ast::ty_param] ty_params, - &def_id id, &ann a) -> @item { - - log("check_item_fn:"); - log_fn(f, i, ty_params); - - assert (fm.contains_key(id)); - find_pre_post_fn(dm, fm, fm.get(id), f); - - ret @respan(sp, ast::item_fn(i, f, ty_params, id, a)); -} - -fn find_pre_post_state_item(&def_map dm, &fn_info_map fm, &fn_info enclosing, - @item i) -> bool { - alt (i.node) { - case (ast::item_const(?id, ?t, ?e, ?di, ?a)) { - ret find_pre_post_state_expr(dm, fm, enclosing, - empty_prestate(num_locals(enclosing)), e); - } - case (ast::item_fn(?id, ?f, ?ps, ?di, ?a)) { - assert (fm.contains_key(di)); - ret find_pre_post_state_fn(dm, fm, fm.get(di), f); - } - case (ast::item_mod(?id, ?m, ?di)) { - ret find_pre_post_state_mod(m); - } - case (ast::item_native_mod(?id, ?nm, ?di)) { - ret find_pre_post_state_native_mod(nm); - } - case (ast::item_ty(_,_,_,_,_)) { - ret false; - } - case (ast::item_tag(_,_,_,_,_)) { - ret false; - } - case (ast::item_obj(?id, ?o, ?ps, ?di, ?a)) { - ret find_pre_post_state_obj(dm, fm, o); - } - } -} - -fn set_prestate_ann(@ann a, prestate pre) -> bool { - assert (! is_none[@ts_ann](a.ts)); - ret set_prestate(get[@ts_ann](a.ts), pre); -} - - -fn extend_prestate_ann(ann a, prestate pre) -> bool { - assert (! is_none[@ts_ann](a.ts)); - ret extend_prestate((get[@ts_ann](a.ts)).states.prestate, pre); -} - -fn set_poststate_ann(ann a, poststate post) -> bool { - assert (! is_none[@ts_ann](a.ts)); - ret set_poststate(get[@ts_ann](a.ts), post); -} - -fn extend_poststate_ann(ann a, poststate post) -> bool { - assert (! is_none[@ts_ann](a.ts)); - ret extend_poststate((*get[@ts_ann](a.ts)).states.poststate, post); -} - -fn set_pre_and_post(&ann a, pre_and_post pp) -> () { - assert (! is_none[@ts_ann](a.ts)); - auto t = *get[@ts_ann](a.ts); - /* log("set_pre_and_post, old ="); - log_pp(t.conditions); - log("new ="); - log_pp(pp); - */ - set_precondition(t, pp.precondition); - set_postcondition(t, pp.postcondition); -} - -fn seq_states(&def_map dm, &fn_info_map fm, &fn_info enclosing, - prestate pres, vec[@expr] exprs) -> tup(bool, poststate) { - auto changed = false; - auto post = pres; - - for (@expr e in exprs) { - changed = find_pre_post_state_expr(dm, fm, enclosing, post, e) - || changed; - post = expr_poststate(e); - } - - ret tup(changed, post); -} - -fn find_pre_post_state_exprs(&def_map dm, - &fn_info_map fm, - &fn_info enclosing, - &prestate pres, - &ann a, &vec[@expr] es) -> bool { - auto res = seq_states(dm, fm, enclosing, pres, es); - auto changed = res._0; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, res._1) || changed; - ret changed; -} - -fn pure_exp(&ann a, &prestate p) -> bool { - auto changed = false; - changed = extend_prestate_ann(a, p) || changed; - changed = extend_poststate_ann(a, p) || changed; - ret changed; -} - -fn find_pre_post_state_loop(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &prestate pres, &@decl d, &@expr index, &block body, &ann a) -> bool { - auto changed = false; - - /* same issues as while */ - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, index) - || changed; - /* in general, would need the intersection of - (poststate of index, poststate of body) */ - changed = find_pre_post_state_block(dm, fm, enclosing, - expr_poststate(index), body) || changed; - auto res_p = intersect_postconds([expr_poststate(index), - block_poststate(body)]); - - changed = extend_poststate_ann(a, res_p) || changed; - ret changed; -} - -fn find_pre_post_state_expr(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &prestate pres, @expr e) -> bool { - auto changed = false; - auto num_local_vars = num_locals(enclosing); - - /* FIXME could get rid of some of the copy/paste */ - alt (e.node) { - case (expr_vec(?elts, _, ?a)) { - ret find_pre_post_state_exprs(dm, fm, enclosing, pres, a, elts); - } - case (expr_tup(?elts, ?a)) { - ret find_pre_post_state_exprs(dm, fm, enclosing, pres, a, - elt_exprs(elts)); - } - case (expr_call(?operator, ?operands, ?a)) { - /* do the prestate for the rator */ - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, operator) - || changed; - /* rands go left-to-right */ - ret(find_pre_post_state_exprs(dm, fm, enclosing, - expr_poststate(operator), a, operands) - || changed); - } - case (expr_spawn(_, _, ?operator, ?operands, ?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, operator); - ret(find_pre_post_state_exprs(dm, fm, enclosing, - expr_poststate(operator), a, operands) - || changed); - } - case (expr_bind(?operator, ?maybe_args, ?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, operator) - || changed; - ret (find_pre_post_state_exprs(dm, fm, enclosing, - expr_poststate(operator), a, cat_options[@expr](maybe_args)) - || changed); - } - case (expr_path(_,?a)) { - ret pure_exp(a, pres); - } - case (expr_log(_,?e,?a)) { - /* factor out the "one exp" pattern */ - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, e); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(e)) || changed; - ret changed; - } - case (expr_chan(?e, ?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, e); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(e)) || changed; - ret changed; - } - case (expr_ext(_, _, _, ?expanded, ?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, expanded); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(expanded)) - || changed; - ret changed; - } - case (expr_put(?maybe_e, ?a)) { - alt (maybe_e) { - case (some[@expr](?arg)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, - pres, arg); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(arg)) - || changed; - ret changed; - } - case (none[@expr]) { - ret pure_exp(a, pres); - } - } - } - case (expr_lit(?l,?a)) { - ret pure_exp(a, pres); - } - case (expr_block(?b,?a)) { - changed = find_pre_post_state_block(dm, fm, enclosing, pres, b) - || changed; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, block_poststate(b)) || changed; - ret changed; - } - case (expr_rec(?fields,?maybe_base,?a)) { - changed = find_pre_post_state_exprs(dm, fm, enclosing, pres, a, - field_exprs(fields)) || changed; - alt (maybe_base) { - case (none[@expr]) { /* do nothing */ } - case (some[@expr](?base)) { - changed = find_pre_post_state_expr - (dm, fm, enclosing, pres, base) || changed; - changed = extend_poststate_ann(a, expr_poststate(base)) - || changed; - } - } - ret changed; - } - case (expr_assign(?lhs, ?rhs, ?a)) { - extend_prestate_ann(a, pres); - - alt (lhs.node) { - case (expr_path(_, ?a_lhs)) { - alt (dm.get(a_lhs.id)) { - case (def_local(?d_id)) { - // assignment to local var - changed = pure_exp(a_lhs, pres) || changed; - changed = find_pre_post_state_expr - (dm, fm, enclosing, pres, rhs) || changed; - changed = extend_poststate_ann - (a, expr_poststate(rhs)) || changed; - ret gen_poststate(enclosing, a, d_id) - || changed; - } - case (_) {} - } - } - case (_) {} - } - // assignment to something that must already have been init'd - changed = find_pre_post_state_expr - (dm, fm, enclosing, pres, lhs) || changed; - changed = find_pre_post_state_expr - (dm, fm, enclosing, expr_poststate(lhs), rhs) || changed; - ret extend_poststate_ann(a, expr_poststate(rhs)) || changed; - } - case (expr_recv(?lhs, ?rhs, ?a)) { - extend_prestate_ann(a, pres); - - alt (lhs.node) { - case (expr_path(?p, ?a_lhs)) { - alt (dm.get(a_lhs.id)) { - case (def_local(?d_id)) { - // receive to local var - changed = pure_exp(a_lhs, pres) || changed; - changed = find_pre_post_state_expr - (dm, fm, enclosing, pres, rhs) || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) - || changed; - ret gen_poststate(enclosing, a, d_id) || changed; - } - case (_) {} - } - } - case (_) {} - } - // receive to something that must already have been init'd - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, lhs) - || changed; - changed = find_pre_post_state_expr - (dm, fm, enclosing, expr_poststate(lhs), rhs) || changed; - ret extend_poststate_ann(a, expr_poststate(rhs)) || changed; - } - - case (expr_ret(?maybe_ret_val, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - set_poststate_ann(a, false_postcond(num_local_vars)); - alt(maybe_ret_val) { - case (none[@expr]) { /* do nothing */ } - case (some[@expr](?ret_val)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, - pres, ret_val) || changed; - } - } - ret changed; - } - case (expr_be(?e, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - set_poststate_ann(a, false_postcond(num_local_vars)); - changed = find_pre_post_state_expr - (dm, fm, enclosing, pres, e) || changed; - ret changed; - } - case (expr_if(?antec, ?conseq, ?maybe_alt, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, antec) - || changed; - changed = find_pre_post_state_block(dm, fm, enclosing, - expr_poststate(antec), conseq) || changed; - alt (maybe_alt) { - case (none[@expr]) { - changed = extend_poststate_ann(a, expr_poststate(antec)) - || changed; - } - case (some[@expr](?altern)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, - expr_poststate(antec), altern) || changed; - auto poststate_res = intersect_postconds - ([block_poststate(conseq), expr_poststate(altern)]); - changed = extend_poststate_ann(a, poststate_res) || changed; - } - } - log("if:"); - log_expr(*e); - log("new prestate:"); - log_bitv(enclosing, pres); - log("new poststate:"); - log_bitv(enclosing, expr_poststate(e)); - - ret changed; - } - case (expr_binary(?bop, ?l, ?r, ?a)) { - /* FIXME: what if bop is lazy? */ - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, l) - || changed; - changed = find_pre_post_state_expr(dm, fm, - enclosing, expr_poststate(l), r) || changed; - changed = extend_poststate_ann(a, expr_poststate(r)) || changed; - ret changed; - } - case (expr_send(?l, ?r, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, l) - || changed; - changed = find_pre_post_state_expr(dm, fm, - enclosing, expr_poststate(l), r) || changed; - changed = extend_poststate_ann(a, expr_poststate(r)) || changed; - ret changed; - } - case (expr_assign_op(?op, ?lhs, ?rhs, ?a)) { - /* quite similar to binary -- should abstract this */ - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, lhs) - || changed; - changed = find_pre_post_state_expr(dm, fm, - enclosing, expr_poststate(lhs), rhs) || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) || changed; - ret changed; - } - case (expr_while(?test, ?body, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - /* to handle general predicates, we need to pass in - pres `intersect` (poststate(a)) - like: auto test_pres = intersect_postconds(pres, expr_postcond(a)); - However, this doesn't work right now because we would be passing - in an all-zero prestate initially - FIXME - maybe need a "don't know" state in addition to 0 or 1? - */ - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, test) - || changed; - changed = find_pre_post_state_block(dm, fm, - enclosing, expr_poststate(test), body) || changed; - changed = extend_poststate_ann(a, - intersect_postconds([expr_poststate(test), - block_poststate(body)])) || changed; - ret changed; - } - case (expr_do_while(?body, ?test, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_block(dm, fm, enclosing, pres, body) - || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, - block_poststate(body), test) || changed; - - /* conservative approximination: if the body of the loop - could break or cont, we revert to the prestate - (TODO: could treat cont differently from break, since - if there's a cont, the test will execute) */ - if (has_nonlocal_exits(body)) { - changed = set_poststate_ann(a, pres) || changed; - } - else { - changed = extend_poststate_ann(a, expr_poststate(test)) - || changed; - } - - ret changed; - } - case (expr_for(?d, ?index, ?body, ?a)) { - ret find_pre_post_state_loop(dm, fm, enclosing, pres, d, index, - body, a); - } - case (expr_for_each(?d, ?index, ?body, ?a)) { - ret find_pre_post_state_loop(dm, fm, enclosing, pres, d, index, - body, a); - } - case (expr_index(?e, ?sub, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, e) - || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, - expr_poststate(e), sub) || changed; - changed = extend_poststate_ann(a, expr_poststate(sub)); - ret changed; - } - case (expr_alt(?e, ?alts, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, e) - || changed; - auto e_post = expr_poststate(e); - auto a_post; - if (vec::len[arm](alts) > 0u) { - a_post = false_postcond(num_local_vars); - for (arm an_alt in alts) { - changed = find_pre_post_state_block(dm, fm, enclosing, e_post, - an_alt.block) || changed; - changed = intersect(a_post, block_poststate(an_alt.block)) - || changed; - } - } - else { - // No alts; poststate is the poststate of the test - a_post = e_post; - } - changed = extend_poststate_ann(a, a_post); - ret changed; - } - case (expr_field(?e,_,?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, e); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(e)) || changed; - ret changed; - } - case (expr_unary(_,?operand,?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, operand) - || changed; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(operand)) - || changed; - ret changed; - } - case (expr_cast(?operand, _, ?a)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, operand) - || changed; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(operand)) - || changed; - ret changed; - } - case (expr_fail(?a)) { - changed = extend_prestate_ann(a, pres) || changed; - /* if execution continues after fail, then everything is true! woo! */ - changed = set_poststate_ann(a, false_postcond(num_local_vars)) - || changed; - ret changed; - } - case (expr_assert(?p, ?a)) { - ret pure_exp(a, pres); - } - case (expr_check(?p, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, p) - || changed; - /* FIXME: update the postcondition to reflect that p holds */ - changed = extend_poststate_ann(a, pres) || changed; - ret changed; - } - case (expr_break(?a)) { - ret pure_exp(a, pres); - } - case (expr_cont(?a)) { - ret pure_exp(a, pres); - } - case (expr_port(?a)) { - ret pure_exp(a, pres); - } - case (expr_self_method(_, ?a)) { - ret pure_exp(a, pres); - } - } -} - -fn find_pre_post_state_stmt(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &prestate pres, @stmt s) -> bool { - auto changed = false; - auto stmt_ann_ = stmt_to_ann(*s); - assert (!is_none[@ts_ann](stmt_ann_)); - auto stmt_ann = *(get[@ts_ann](stmt_ann_)); - log("*At beginning: stmt = "); - log_stmt(*s); - log("*prestate = "); - log(bitv::to_str(stmt_ann.states.prestate)); - log("*poststate ="); - log(bitv::to_str(stmt_ann.states.poststate)); - log("*changed ="); - log(changed); - - alt (s.node) { - case (stmt_decl(?adecl, ?a)) { - alt (adecl.node) { - case (ast::decl_local(?alocal)) { - alt (alocal.init) { - case (some[ast::initializer](?an_init)) { - changed = extend_prestate(stmt_ann.states.prestate, pres) - || changed; - changed = find_pre_post_state_expr - (dm, fm, enclosing, pres, an_init.expr) || changed; - changed = extend_poststate(stmt_ann.states.poststate, - expr_poststate(an_init.expr)) - || changed; - changed = gen_poststate(enclosing, a, alocal.id) || changed; - log("Summary: stmt = "); - log_stmt(*s); - log("prestate = "); - log(bitv::to_str(stmt_ann.states.prestate)); - log_bitv(enclosing, stmt_ann.states.prestate); - log("poststate ="); - log_bitv(enclosing, stmt_ann.states.poststate); - log("changed ="); - log(changed); - - ret changed; - } - case (none[ast::initializer]) { - changed = extend_prestate(stmt_ann.states.prestate, pres) - || changed; - changed = extend_poststate(stmt_ann.states.poststate, pres) - || changed; - ret changed; - } - } - } - case (ast::decl_item(?an_item)) { - changed = extend_prestate(stmt_ann.states.prestate, pres) - || changed; - changed = extend_poststate(stmt_ann.states.poststate, pres) - || changed; - ret find_pre_post_state_item(dm, fm, enclosing, an_item) - || changed; - } - } - } - case (stmt_expr(?e, _)) { - changed = find_pre_post_state_expr(dm, fm, enclosing, pres, e) - || changed; - changed = extend_prestate(stmt_ann.states.prestate, expr_prestate(e)) - || changed; - changed = extend_poststate(stmt_ann.states.poststate, - expr_poststate(e)) || changed; - /* - log("Summary: stmt = "); - log_stmt(*s); - log("prestate = "); - log(bitv::to_str(stmt_ann.states.prestate)); - log_bitv(enclosing, stmt_ann.states.prestate); - log("poststate ="); - log(bitv::to_str(stmt_ann.states.poststate)); - log_bitv(enclosing, stmt_ann.states.poststate); - log("changed ="); - log(changed); - */ - ret changed; - } - case (_) { ret false; } - } -} - -/* Updates the pre- and post-states of statements in the block, - returns a boolean flag saying whether any pre- or poststates changed */ -fn find_pre_post_state_block(&def_map dm, &fn_info_map fm, &fn_info enclosing, - &prestate pres0, &block b) - -> bool { - - auto changed = false; - auto num_local_vars = num_locals(enclosing); - - /* First, set the pre-states and post-states for every expression */ - auto pres = pres0; - - /* Iterate over each stmt. The new prestate is . The poststate - consist of improving with whatever variables this stmt initializes. - Then becomes the new poststate. */ - for (@stmt s in b.node.stmts) { - changed = find_pre_post_state_stmt(dm, fm, enclosing, pres, s) || changed; - pres = stmt_poststate(*s, num_local_vars); - } - - auto post = pres; - - alt (b.node.expr) { - case (none[@expr]) {} - case (some[@expr](?e)) { - changed = find_pre_post_state_expr(dm,fm, enclosing, pres, e) - || changed; - post = expr_poststate(e); - } - } - - /* - log_err("block:"); - log_block_err(b); - log_err("has non-local exits?"); - log_err(has_nonlocal_exits(b)); - */ - - /* conservative approximation: if a block contains a break - or cont, we assume nothing about the poststate */ - if (has_nonlocal_exits(b)) { - post = pres0; - } - - set_prestate_ann(@b.node.a, pres0); - set_poststate_ann(b.node.a, post); - - - log("For block:"); - log_block(b); - log("poststate = "); - log_states(block_states(b)); - log("pres0:"); - log_bitv(enclosing, pres0); - log("post:"); - log_bitv(enclosing, post); - - - ret changed; -} - -fn find_pre_post_state_fn(&def_map dm, &fn_info_map f_info, &fn_info fi, - &ast::_fn f) -> bool { - /* FIXME: where do we set args as being initialized? - What about for methods? */ - auto num_local_vars = num_locals(fi); - ret find_pre_post_state_block(dm, f_info, fi, - empty_prestate(num_local_vars), f.body); -} - -fn check_states_expr(fn_info enclosing, @expr e) -> () { - let precond prec = expr_precond(e); - let prestate pres = expr_prestate(e); - - if (!implies(pres, prec)) { - log_err("check_states_expr: Unsatisfied precondition constraint for "); - log_expr_err(*e); - log_err("Precondition: "); - log_bitv_err(enclosing, prec); - log_err("Prestate: "); - log_bitv_err(enclosing, pres); - fail; - } -} - -fn check_states_stmt(fn_info enclosing, &stmt s) -> () { - alt (stmt_to_ann(s)) { - case (none[@ts_ann]) { - ret; - } - case (some[@ts_ann](?a)) { - let precond prec = ann_precond(*a); - let prestate pres = ann_prestate(*a); - - /* - log("check_states_stmt:"); - log_stmt(s); - log("prec = "); - log_bitv(enclosing, prec); - log("pres = "); - log_bitv(enclosing, pres); - */ - - if (!implies(pres, prec)) { - log_err("check_states_stmt: " - + "Unsatisfied precondition constraint for "); - log_stmt_err(s); - log_err("Precondition: "); - log_bitv_err(enclosing, prec); - log_err("Prestate: "); - log_bitv_err(enclosing, pres); - fail; - } - } - } -} - -fn check_states_against_conditions(fn_info enclosing, &ast::_fn f) -> () { - fn do_one_(fn_info i, &@stmt s) -> () { - check_states_stmt(i, *s); - } - auto do_one = bind do_one_(enclosing, _); - - vec::map[@stmt, ()](do_one, f.body.node.stmts); - fn do_inner_(fn_info i, &@expr e) -> () { - check_states_expr(i, e); - } - auto do_inner = bind do_inner_(enclosing, _); - option::map[@expr, ()](do_inner, f.body.node.expr); - -} - -fn check_fn_states(&def_map dm, &fn_info_map f_info_map, &fn_info f_info, - &ast::_fn f) -> () { - /* Compute the pre- and post-states for this function */ - // (Fixpoint iteration) - while (find_pre_post_state_fn(dm, f_info_map, f_info, f)) {} - - /* Now compare each expr's pre-state to its precondition - and post-state to its postcondition */ - check_states_against_conditions(f_info, f); -} - -fn check_item_fn_state(def_map dm, &fn_info_map f_info_map, &span sp, - &ident i, &ast::_fn f, &vec[ast::ty_param] ty_params, - &def_id id, &ann a) -> @item { - - /* Look up the var-to-bit-num map for this function */ - assert (f_info_map.contains_key(id)); - auto f_info = f_info_map.get(id); - - check_fn_states(dm, f_info_map, f_info, f); - - /* Rebuild the same function */ - ret @respan(sp, ast::item_fn(i, f, ty_params, id, a)); -} - -fn check_method_states(&def_map dm, &fn_info_map f_info_map, @method m) { - assert (f_info_map.contains_key(m.node.id)); - auto f_info = f_info_map.get(m.node.id); - check_fn_states(dm, f_info_map, f_info, m.node.meth); -} - -fn check_obj_state(def_map dm, &fn_info_map f_info_map, - &vec[obj_field] fields, &vec[@method] methods, - &option::t[@method] dtor) -> ast::_obj { - fn one(def_map dm, fn_info_map fm, &@method m) -> () { - ret check_method_states(dm, fm, m); - } - auto f = bind one(dm, f_info_map,_); - vec::map[@method, ()](f, methods); - option::map[@method, ()](f, dtor); - ret rec(fields=fields, methods=methods, dtor=dtor); -} - -fn init_ann(&fn_info fi, &ann a) -> ann { - ret rec(id=a.id, ty=a.ty, tps=a.tps, - ts=some[@ts_ann](@empty_ann(num_locals(fi)))); -} - -fn init_blank_ann(&() ignore, &ann a) -> ann { - ret rec(id=a.id, ty=a.ty, tps=a.tps, ts=some[@ts_ann](@empty_ann(0u))); -} - -fn init_block(&fn_info fi, &span sp, &block_ b) -> block { - log("init_block:"); - log_block(respan(sp, b)); - - auto fld0 = fold::new_identity_fold[fn_info](); - - fld0 = @rec(fold_ann = bind init_ann(_,_) with *fld0); - ret fold::fold_block[fn_info](fi, fld0, respan(sp, b)); -} - -fn item_fn_anns(&fn_info_map fm, &span sp, ident i, &ast::_fn f, - vec[ast::ty_param] ty_params, def_id id, ann a) -> @item { - - assert (fm.contains_key(id)); - auto f_info = fm.get(id); - - log(i + " has " + uistr(num_locals(f_info)) + " local vars"); - - auto fld0 = fold::new_identity_fold[fn_info](); - - fld0 = @rec(fold_ann = bind init_ann(_,_) - with *fld0); - - ret fold::fold_item[fn_info] - (f_info, fld0, @respan(sp, item_fn(i, f, ty_params, id, a))); -} - -/* This is painstakingly written as an explicit recursion b/c the - standard ast::fold doesn't traverse in the correct order: - consider - fn foo() { - fn bar() { - auto x = 5; - log(x); - } - } - With fold, first bar() would be processed and its subexps would - correctly be annotated with length-1 bit vectors. - But then, the process would be repeated with (fn bar()...) as - a subexp of foo, which has 0 local variables -- so then - the body of bar() would be incorrectly annotated with length-0 bit - vectors. */ -fn annotate_exprs(&fn_info_map fm, &vec[@expr] es) -> vec[@expr] { - fn one(fn_info_map fm, &@expr e) -> @expr { - ret annotate_expr(fm, e); - } - auto f = bind one(fm,_); - ret vec::map[@expr, @expr](f, es); -} -fn annotate_elts(&fn_info_map fm, &vec[elt] es) -> vec[elt] { - fn one(fn_info_map fm, &elt e) -> elt { - ret rec(mut=e.mut, - expr=annotate_expr(fm, e.expr)); - } - auto f = bind one(fm,_); - ret vec::map[elt, elt](f, es); -} -fn annotate_fields(&fn_info_map fm, &vec[field] fs) -> vec[field] { - fn one(fn_info_map fm, &field f) -> field { - ret rec(mut=f.mut, - ident=f.ident, - expr=annotate_expr(fm, f.expr)); - } - auto f = bind one(fm,_); - ret vec::map[field, field](f, fs); -} -fn annotate_option_exp(&fn_info_map fm, &option::t[@expr] o) - -> option::t[@expr] { - fn one(fn_info_map fm, &@expr e) -> @expr { - ret annotate_expr(fm, e); - } - auto f = bind one(fm,_); - ret option::map[@expr, @expr](f, o); -} -fn annotate_option_exprs(&fn_info_map fm, &vec[option::t[@expr]] es) - -> vec[option::t[@expr]] { - fn one(fn_info_map fm, &option::t[@expr] o) -> option::t[@expr] { - ret annotate_option_exp(fm, o); - } - auto f = bind one(fm,_); - ret vec::map[option::t[@expr], option::t[@expr]](f, es); -} -fn annotate_decl(&fn_info_map fm, &@decl d) -> @decl { - auto d1 = d.node; - alt (d.node) { - case (decl_local(?l)) { - alt(l.init) { - case (some[initializer](?init)) { - let option::t[initializer] an_i = - some[initializer] - (rec(expr=annotate_expr(fm, init.expr) - with init)); - let @local new_l = @rec(init=an_i with *l); - d1 = decl_local(new_l); - } - case (_) { /* do nothing */ } - } - } - case (decl_item(?item)) { - d1 = decl_item(annotate_item(fm, item)); - } - } - ret @respan(d.span, d1); -} -fn annotate_alts(&fn_info_map fm, &vec[arm] alts) -> vec[arm] { - fn one(fn_info_map fm, &arm a) -> arm { - ret rec(pat=a.pat, - block=annotate_block(fm, a.block)); - } - auto f = bind one(fm,_); - ret vec::map[arm, arm](f, alts); - -} -fn annotate_expr(&fn_info_map fm, &@expr e) -> @expr { - auto e1 = e.node; - alt (e.node) { - case (expr_vec(?es, ?m, ?a)) { - e1 = expr_vec(annotate_exprs(fm, es), m, a); - } - case (expr_tup(?es, ?a)) { - e1 = expr_tup(annotate_elts(fm, es), a); - } - case (expr_rec(?fs, ?maybe_e, ?a)) { - e1 = expr_rec(annotate_fields(fm, fs), - annotate_option_exp(fm, maybe_e), a); - } - case (expr_call(?e, ?es, ?a)) { - e1 = expr_call(annotate_expr(fm, e), - annotate_exprs(fm, es), a); - } - case (expr_self_method(_,_)) { - // no change - } - case (expr_bind(?e, ?maybe_es, ?a)) { - e1 = expr_bind(annotate_expr(fm, e), - annotate_option_exprs(fm, maybe_es), - a); - } - case (expr_spawn(?s, ?maybe_s, ?e, ?es, ?a)) { - e1 = expr_spawn(s, maybe_s, annotate_expr(fm, e), - annotate_exprs(fm, es), a); - } - case (expr_binary(?bop, ?w, ?x, ?a)) { - e1 = expr_binary(bop, annotate_expr(fm, w), - annotate_expr(fm, x), a); - } - case (expr_unary(?uop, ?w, ?a)) { - e1 = expr_unary(uop, annotate_expr(fm, w), a); - } - case (expr_lit(_,_)) { - /* no change */ - } - case (expr_cast(?e,?t,?a)) { - e1 = expr_cast(annotate_expr(fm, e), t, a); - } - case (expr_if(?e, ?b, ?maybe_e, ?a)) { - e1 = expr_if(annotate_expr(fm, e), - annotate_block(fm, b), - annotate_option_exp(fm, maybe_e), a); - } - case (expr_while(?e, ?b, ?a)) { - e1 = expr_while(annotate_expr(fm, e), - annotate_block(fm, b), a); - } - case (expr_for(?d, ?e, ?b, ?a)) { - e1 = expr_for(annotate_decl(fm, d), - annotate_expr(fm, e), - annotate_block(fm, b), a); - } - case (expr_for_each(?d, ?e, ?b, ?a)) { - e1 = expr_for_each(annotate_decl(fm, d), - annotate_expr(fm, e), - annotate_block(fm, b), a); - } - case (expr_do_while(?b, ?e, ?a)) { - e1 = expr_do_while(annotate_block(fm, b), - annotate_expr(fm, e), a); - } - case (expr_alt(?e, ?alts, ?a)) { - e1 = expr_alt(annotate_expr(fm, e), - annotate_alts(fm, alts), a); - } - case (expr_block(?b, ?a)) { - e1 = expr_block(annotate_block(fm, b), a); - } - case (expr_assign(?l, ?r, ?a)) { - e1 = expr_assign(annotate_expr(fm, l), annotate_expr(fm, r), a); - } - case (expr_assign_op(?bop, ?l, ?r, ?a)) { - e1 = expr_assign_op(bop, - annotate_expr(fm, l), annotate_expr(fm, r), a); - } - case (expr_send(?l, ?r, ?a)) { - e1 = expr_send(annotate_expr(fm, l), - annotate_expr(fm, r), a); - } - case (expr_recv(?l, ?r, ?a)) { - e1 = expr_recv(annotate_expr(fm, l), - annotate_expr(fm, r), a); - } - case (expr_field(?e, ?i, ?a)) { - e1 = expr_field(annotate_expr(fm, e), - i, a); - } - case (expr_index(?e, ?sub, ?a)) { - e1 = expr_index(annotate_expr(fm, e), - annotate_expr(fm, sub), a); - } - case (expr_path(_,_)) { - /* no change */ - } - case (expr_ext(?p, ?es, ?s_opt, ?e, ?a)) { - e1 = expr_ext(p, annotate_exprs(fm, es), - s_opt, - annotate_expr(fm, e), a); - } - /* no change, next 3 cases */ - case (expr_fail(_)) { } - case (expr_break(_)) { } - case (expr_cont(_)) { } - case (expr_ret(?maybe_e, ?a)) { - e1 = expr_ret(annotate_option_exp(fm, maybe_e), a); - } - case (expr_put(?maybe_e, ?a)) { - e1 = expr_put(annotate_option_exp(fm, maybe_e), a); - } - case (expr_be(?e, ?a)) { - e1 = expr_be(annotate_expr(fm, e), a); - } - case (expr_log(?n, ?e, ?a)) { - e1 = expr_log(n, annotate_expr(fm, e), a); - } - case (expr_assert(?e, ?a)) { - e1 = expr_assert(annotate_expr(fm, e), a); - } - case (expr_check(?e, ?a)) { - e1 = expr_check(annotate_expr(fm, e), a); - } - case (expr_port(_)) { /* no change */ } - case (expr_chan(?e, ?a)) { - e1 = expr_chan(annotate_expr(fm, e), a); - } - } - ret @respan(e.span, e1); -} - -fn annotate_stmt(&fn_info_map fm, &@stmt s) -> @stmt { - alt (s.node) { - case (stmt_decl(?d, ?a)) { - ret @respan(s.span, stmt_decl(annotate_decl(fm, d), a)); - } - case (stmt_expr(?e, ?a)) { - ret @respan(s.span, stmt_expr(annotate_expr(fm, e), a)); - } - } -} -fn annotate_block(&fn_info_map fm, &block b) -> block { - let vec[@stmt] new_stmts = []; - - for (@stmt s in b.node.stmts) { - auto new_s = annotate_stmt(fm, s); - vec::push[@stmt](new_stmts, new_s); - } - fn ann_e(fn_info_map fm, &@expr e) -> @expr { - ret annotate_expr(fm, e); - } - auto f = bind ann_e(fm,_); - - auto new_e = option::map[@expr, @expr](f, b.node.expr); - - ret respan(b.span, - rec(stmts=new_stmts, expr=new_e with b.node)); -} -fn annotate_fn(&fn_info_map fm, &ast::_fn f) -> ast::_fn { - // subexps have *already* been annotated based on - // f's number-of-locals - ret rec(body=annotate_block(fm, f.body) with f); -} -fn annotate_mod(&fn_info_map fm, &ast::_mod m) -> ast::_mod { - let vec[@item] new_items = []; - - for (@item i in m.items) { - auto new_i = annotate_item(fm, i); - vec::push[@item](new_items, new_i); - } - ret rec(items=new_items with m); -} -fn annotate_method(&fn_info_map fm, &@method m) -> @method { - auto f_info = get_fn_info(fm, m.node.id); - auto fld0 = fold::new_identity_fold[fn_info](); - fld0 = @rec(fold_ann = bind init_ann(_,_) - with *fld0); - auto outer = fold::fold_method[fn_info](f_info, fld0, m); - auto new_fn = annotate_fn(fm, outer.node.meth); - ret @respan(m.span, - rec(meth=new_fn with m.node)); -} - -fn annotate_obj(&fn_info_map fm, &ast::_obj o) -> ast::_obj { - fn one(fn_info_map fm, &@method m) -> @method { - ret annotate_method(fm, m); - } - auto f = bind one(fm,_); - auto new_methods = vec::map[@method, @method](f, o.methods); - auto new_dtor = option::map[@method, @method](f, o.dtor); - ret rec(methods=new_methods, dtor=new_dtor with o); -} - - -// Only annotates the components of the item recursively. -fn annotate_item_inner(&fn_info_map fm, &@ast::item item) -> @ast::item { - alt (item.node) { - /* FIXME can't skip this case -- exprs contain blocks contain stmts, - which contain decls */ - case (ast::item_const(_,_,_,_,_)) { - // this has already been annotated by annotate_item - ret item; - } - case (ast::item_fn(?ident, ?ff, ?tps, ?id, ?ann)) { - ret @respan(item.span, - ast::item_fn(ident, annotate_fn(fm, ff), - tps, id, ann)); - } - case (ast::item_mod(?ident, ?mm, ?id)) { - ret @respan(item.span, - ast::item_mod(ident, annotate_mod(fm, mm), id)); - } - case (ast::item_native_mod(?ident, ?mm, ?id)) { - ret item; - } - case (ast::item_ty(_,_,_,_,_)) { - ret item; - } - case (ast::item_tag(_,_,_,_,_)) { - ret item; - } - case (ast::item_obj(?ident, ?ob, ?tps, ?odid, ?ann)) { - ret @respan(item.span, - ast::item_obj(ident, annotate_obj(fm, ob), tps, odid, ann)); - } - } -} - -fn annotate_item(&fn_info_map fm, &@ast::item item) -> @ast::item { - // Using a fold, recursively set all anns in this item - // to be blank. - // *Then*, call annotate_item recursively to do the right - // thing for any nested items inside this one. - - alt (item.node) { - case (ast::item_const(_,_,_,_,_)) { - auto fld0 = fold::new_identity_fold[()](); - fld0 = @rec(fold_ann = bind init_blank_ann(_,_) - with *fld0); - ret fold::fold_item[()]((), fld0, item); - } - case (ast::item_fn(?i,?ff,?tps,?id,?ann)) { - auto f_info = get_fn_info(fm, id); - auto fld0 = fold::new_identity_fold[fn_info](); - fld0 = @rec(fold_ann = bind init_ann(_,_) - with *fld0); - auto outer = fold::fold_item[fn_info](f_info, fld0, item); - // now recurse into any nested items - ret annotate_item_inner(fm, outer); - } - case (ast::item_mod(?i, ?mm, ?id)) { - auto fld0 = fold::new_identity_fold[()](); - fld0 = @rec(fold_ann = bind init_blank_ann(_,_) - with *fld0); - auto outer = fold::fold_item[()]((), fld0, item); - ret annotate_item_inner(fm, outer); - } - case (ast::item_native_mod(?i, ?nm, ?id)) { - ret item; - } - case (ast::item_ty(_,_,_,_,_)) { - ret item; - } - case (ast::item_tag(_,_,_,_,_)) { - ret item; - } - case (ast::item_obj(?i,?ob,?tps,?odid,?ann)) { - auto fld0 = fold::new_identity_fold[()](); - fld0 = @rec(fold_ann = bind init_blank_ann(_,_) - with *fld0); - auto outer = fold::fold_item[()]((), fld0, item); - ret annotate_item_inner(fm, outer); - } - } -} - -fn annotate_module(&fn_info_map fm, &ast::_mod module) -> ast::_mod { - let vec[@item] new_items = []; - - for (@item i in module.items) { - auto new_item = annotate_item(fm, i); - vec::push[@item](new_items, new_item); - } - - ret rec(items = new_items with module); -} - -fn annotate_crate(&fn_info_map fm, &@ast::crate crate) -> @ast::crate { - ret @respan(crate.span, - rec(module = annotate_module(fm, crate.node.module) - with crate.node)); -} - -fn check_crate(@ast::crate crate, def_map dm) -> @ast::crate { - /* Build the global map from function id to var-to-bit-num-map */ - auto fm = mk_f_to_fn_info(crate); - - /* Add a blank ts_ann to every statement (and expression) */ - auto with_anns = annotate_crate(fm, crate); - - /* Compute the pre and postcondition for every subexpression */ - auto fld = fold::new_identity_fold[fn_info_map](); - fld = @rec(fold_item_fn = bind check_item_fn(dm,_,_,_,_,_,_,_) with *fld); - auto with_pre_postconditions = fold::fold_crate[fn_info_map] - (fm, fld, with_anns); - - auto fld1 = fold::new_identity_fold[fn_info_map](); - - fld1 = @rec(fold_item_fn = bind check_item_fn_state(dm,_,_,_,_,_,_,_), - fold_obj = bind check_obj_state(dm,_,_,_,_) - with *fld1); - - ret fold::fold_crate[fn_info_map](fm, fld1, - with_pre_postconditions); -} - -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -// From 1cd5db95ae8f98efe5198e2d038029cfbc86c2df Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:34:52 -0700 Subject: [PATCH 04/10] Tell Makefile to look an extra level deep for dependencies --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index f9700ed79df71..3f44401dfe048 100644 --- a/Makefile.in +++ b/Makefile.in @@ -137,7 +137,7 @@ STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/lib/,*.rc *.rs */*.rs)) COMPILER_CRATE := $(S)src/comp/rustc.rc COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \ - rustc.rc *.rs */*.rs)) + rustc.rc *.rs */*.rs */*/*.rs)) ###################################################################### # Main target dependency variables From a74ed0732c82034bc14b0000c674b328c1eb2b4f Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:38:38 -0700 Subject: [PATCH 05/10] add a bunch more logging things --- src/comp/util/common.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index deb73c84a7cba..8d62e27f5bc63 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -4,6 +4,7 @@ import std::uint; import std::int; import std::vec; import std::option::none; +import std::option::some; import front::ast; import front::ast::ty; import front::ast::pat; @@ -16,6 +17,7 @@ import std::io::stdout; import std::io::str_writer; import std::io::string_writer; import pretty::pprust::print_block; +import pretty::pprust::print_item; import pretty::pprust::print_expr; import pretty::pprust::print_decl; import pretty::pprust::print_fn; @@ -171,6 +173,17 @@ fn block_to_str(&ast::block b) -> str { ret s.get_str(); } +fn item_to_str(&@ast::item i) -> str { + let str_writer s = string_writer(); + auto out_ = mkstate(s.get_writer(), 80u); + auto out = @rec(s=out_, + comments=none[vec[front::lexer::cmnt]], + mutable cur_cmnt=0u); + + print_item(out, i); + ret s.get_str(); +} + fn log_block(&ast::block b) -> () { log(block_to_str(b)); } @@ -179,6 +192,21 @@ fn log_block_err(&ast::block b) -> () { log_err(block_to_str(b)); } +fn log_item_err(&@ast::item i) -> () { + log_err(item_to_str(i)); +} + +fn log_ann(&ast::ann a) -> () { + alt (a) { + case (ast::ann_none(_)) { + log("ann_none"); + } + case (ast::ann_type(_,_,_,_)) { + log("ann_type"); + } + } +} + fn fun_to_str(&ast::_fn f, str name, vec[ast::ty_param] params) -> str { let str_writer s = string_writer(); auto out_ = mkstate(s.get_writer(), 80u); @@ -286,6 +314,13 @@ fn has_nonlocal_exits(&ast::block b) -> bool { ret (has_exits.size() > 0u); } +fn local_rhs_span(&@ast::local l, &ast::span def) -> ast::span { + alt (l.init) { + case (some[ast::initializer](?i)) { ret i.expr.span; } + case (_) { ret def; } + } +} + // // Local Variables: // mode: rust From c9bd1acbf3d580911717a63b91096d0bff9c2074 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:35:16 -0700 Subject: [PATCH 06/10] Make trans use span_err for the dreaded "ty_var in trans::type_of" error This required quite a bit of tiresome plumbing about of spans. On the bright side, now other errors can be converted to span_err too. Includes test cases. --- src/comp/middle/trans.rs | 269 +++++++++++++---------- src/test/compile-fail/vector-no-ann-2.rs | 5 + src/test/compile-fail/vector-no-ann.rs | 5 + 3 files changed, 158 insertions(+), 121 deletions(-) create mode 100644 src/test/compile-fail/vector-no-ann-2.rs create mode 100644 src/test/compile-fail/vector-no-ann.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d53ad5b8c85b8..dbd5217c96185 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -26,6 +26,7 @@ import util::common; import util::common::istr; import util::common::new_def_hash; import util::common::new_str_hash; +import util::common::local_rhs_span; import lib::llvm::llvm; import lib::llvm::builder; @@ -155,6 +156,7 @@ state type fn_ctxt = rec(ValueRef llfn, hashmap[ast::def_id, ValueRef] llupvars, mutable vec[ValueRef] lltydescs, hashmap[ty::t, derived_tydesc_info] derived_tydescs, + ast::span sp, @local_ctxt lcx); tag cleanup { @@ -173,6 +175,7 @@ state type block_ctxt = rec(BasicBlockRef llbb, block_parent parent, block_kind kind, mutable vec[cleanup] cleanups, + ast::span sp, @fn_ctxt fcx); // FIXME: we should be able to use option::t[@block_parent] here but @@ -398,8 +401,8 @@ fn T_glue_fn(&type_names tn) -> TypeRef { ret t; } -fn T_dtor(&@crate_ctxt ccx, TypeRef llself_ty) -> TypeRef { - ret type_of_fn_full(ccx, ast::proto_fn, some[TypeRef](llself_ty), +fn T_dtor(&@crate_ctxt ccx, &ast::span sp, TypeRef llself_ty) -> TypeRef { + ret type_of_fn_full(ccx, sp, ast::proto_fn, some[TypeRef](llself_ty), vec::empty[ty::arg](), ty::mk_nil(ccx.tcx), 0u); } @@ -621,17 +624,18 @@ fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); } // return value was always meaningless in that case anyhow). Beware! // // TODO: Enforce via a predicate. -fn type_of(&@crate_ctxt cx, &ty::t t) -> TypeRef { +fn type_of(&@crate_ctxt cx, &ast::span sp, &ty::t t) -> TypeRef { if (ty::type_has_dynamic_size(cx.tcx, t)) { - log_err "type_of() called on a type with dynamic size: " + - ty::ty_to_str(cx.tcx, t); + cx.sess.span_err (sp, + "type_of() called on a type with dynamic size: " + + ty::ty_to_str(cx.tcx, t)); fail; } - ret type_of_inner(cx, t); + ret type_of_inner(cx, sp, t); } -fn type_of_explicit_args(&@crate_ctxt cx, +fn type_of_explicit_args(&@crate_ctxt cx, &ast::span sp, &vec[ty::arg] inputs) -> vec[TypeRef] { let vec[TypeRef] atys = []; for (ty::arg arg in inputs) { @@ -642,10 +646,10 @@ fn type_of_explicit_args(&@crate_ctxt cx, let TypeRef t; alt (arg.mode) { case (ty::mo_alias) { - t = T_ptr(type_of_inner(cx, arg.ty)); + t = T_ptr(type_of_inner(cx, sp, arg.ty)); } case (_) { - t = type_of_inner(cx, arg.ty); + t = type_of_inner(cx, sp, arg.ty); } } atys += [t]; @@ -662,6 +666,7 @@ fn type_of_explicit_args(&@crate_ctxt cx, // - trans_args fn type_of_fn_full(&@crate_ctxt cx, + &ast::span sp, ast::proto proto, &option::t[TypeRef] obj_self, &vec[ty::arg] inputs, @@ -673,7 +678,7 @@ fn type_of_fn_full(&@crate_ctxt cx, if (ty::type_has_dynamic_size(cx.tcx, output)) { atys += [T_typaram_ptr(cx.tn)]; } else { - atys += [T_ptr(type_of_inner(cx, output))]; + atys += [T_ptr(type_of_inner(cx, sp, output))]; } // Arg 1: task pointer. @@ -705,28 +710,29 @@ fn type_of_fn_full(&@crate_ctxt cx, // argument. atys += [T_fn_pair(cx.tn, - type_of_fn_full(cx, ast::proto_fn, none[TypeRef], + type_of_fn_full(cx, sp, ast::proto_fn, none[TypeRef], [rec(mode=ty::mo_alias, ty=output)], ty::mk_nil(cx.tcx), 0u))]; } // ... then explicit args. - atys += type_of_explicit_args(cx, inputs); + atys += type_of_explicit_args(cx, sp, inputs); ret T_fn(atys, llvm::LLVMVoidType()); } fn type_of_fn(&@crate_ctxt cx, + &ast::span sp, ast::proto proto, &vec[ty::arg] inputs, &ty::t output, uint ty_param_count) -> TypeRef { - ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output, + ret type_of_fn_full(cx, sp, proto, none[TypeRef], inputs, output, ty_param_count); } -fn type_of_native_fn(&@crate_ctxt cx, ast::native_abi abi, +fn type_of_native_fn(&@crate_ctxt cx, &ast::span sp, ast::native_abi abi, &vec[ty::arg] inputs, &ty::t output, uint ty_param_count) -> TypeRef { @@ -740,11 +746,11 @@ fn type_of_native_fn(&@crate_ctxt cx, ast::native_abi abi, i += 1u; } } - atys += type_of_explicit_args(cx, inputs); - ret T_fn(atys, type_of_inner(cx, output)); + atys += type_of_explicit_args(cx, sp, inputs); + ret T_fn(atys, type_of_inner(cx, sp, output)); } -fn type_of_inner(&@crate_ctxt cx, &ty::t t) -> TypeRef { +fn type_of_inner(&@crate_ctxt cx, &ast::span sp, &ty::t t) -> TypeRef { // Check the cache. if (cx.lltypes.contains_key(t)) { ret cx.lltypes.get(t); @@ -780,41 +786,41 @@ fn type_of_inner(&@crate_ctxt cx, &ty::t t) -> TypeRef { if (ty::type_has_dynamic_size(cx.tcx, t)) { llty = T_opaque_tag(cx.tn); } else { - auto size = static_size_of_tag(cx, t); + auto size = static_size_of_tag(cx, sp, t); llty = T_tag(cx.tn, size); } } case (ty::ty_box(?mt)) { - llty = T_ptr(T_box(type_of_inner(cx, mt.ty))); + llty = T_ptr(T_box(type_of_inner(cx, sp, mt.ty))); } case (ty::ty_vec(?mt)) { - llty = T_ptr(T_vec(type_of_inner(cx, mt.ty))); + llty = T_ptr(T_vec(type_of_inner(cx, sp, mt.ty))); } case (ty::ty_port(?t)) { - llty = T_ptr(T_port(type_of_inner(cx, t))); + llty = T_ptr(T_port(type_of_inner(cx, sp, t))); } case (ty::ty_chan(?t)) { - llty = T_ptr(T_chan(type_of_inner(cx, t))); + llty = T_ptr(T_chan(type_of_inner(cx, sp, t))); } case (ty::ty_tup(?elts)) { let vec[TypeRef] tys = []; for (ty::mt elt in elts) { - tys += [type_of_inner(cx, elt.ty)]; + tys += [type_of_inner(cx, sp, elt.ty)]; } llty = T_struct(tys); } case (ty::ty_rec(?fields)) { let vec[TypeRef] tys = []; for (ty::field f in fields) { - tys += [type_of_inner(cx, f.mt.ty)]; + tys += [type_of_inner(cx, sp, f.mt.ty)]; } llty = T_struct(tys); } case (ty::ty_fn(?proto, ?args, ?out)) { - llty = T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out, 0u)); + llty = T_fn_pair(cx.tn, type_of_fn(cx, sp, proto, args, out, 0u)); } case (ty::ty_native_fn(?abi, ?args, ?out)) { - auto nft = native_fn_wrapper_type(cx, 0u, t); + auto nft = native_fn_wrapper_type(cx, sp, 0u, t); llty = T_fn_pair(cx.tn, nft); } case (ty::ty_obj(?meths)) { @@ -824,7 +830,7 @@ fn type_of_inner(&@crate_ctxt cx, &ty::t t) -> TypeRef { let vec[TypeRef] mtys = [T_ptr(T_i8())]; for (ty::method m in meths) { let TypeRef mty = - type_of_fn_full(cx, m.proto, + type_of_fn_full(cx, sp, m.proto, some[TypeRef](self_ty), m.inputs, m.output, 0u); mtys += [T_ptr(mty)]; @@ -839,8 +845,7 @@ fn type_of_inner(&@crate_ctxt cx, &ty::t t) -> TypeRef { llty = abs_pair; } case (ty::ty_var(_)) { - log_err "ty_var in trans::type_of"; - fail; + cx.tcx.sess.span_err(sp, "ty_var in trans::type_of"); } case (ty::ty_param(_)) { llty = T_i8(); @@ -862,7 +867,7 @@ fn type_of_inner(&@crate_ctxt cx, &ty::t t) -> TypeRef { ret llty; } -fn type_of_arg(@local_ctxt cx, &ty::arg arg) -> TypeRef { +fn type_of_arg(@local_ctxt cx, &ast::span sp, &ty::arg arg) -> TypeRef { alt (ty::struct(cx.ccx.tcx, arg.ty)) { case (ty::ty_param(_)) { if (arg.mode == ty::mo_alias) { @@ -876,25 +881,26 @@ fn type_of_arg(@local_ctxt cx, &ty::arg arg) -> TypeRef { auto typ; if (arg.mode == ty::mo_alias) { - typ = T_ptr(type_of_inner(cx.ccx, arg.ty)); + typ = T_ptr(type_of_inner(cx.ccx, sp, arg.ty)); } else { - typ = type_of_inner(cx.ccx, arg.ty); + typ = type_of_inner(cx.ccx, sp, arg.ty); } ret typ; } -fn type_of_ty_param_count_and_ty(@local_ctxt lcx, +fn type_of_ty_param_count_and_ty(@local_ctxt lcx, &ast::span sp, &ty::ty_param_count_and_ty tpt) -> TypeRef { alt (ty::struct(lcx.ccx.tcx, tpt._1)) { case (ty::ty_fn(?proto, ?inputs, ?output)) { - auto llfnty = type_of_fn(lcx.ccx, proto, inputs, output, tpt._0); + auto llfnty = type_of_fn(lcx.ccx, sp, proto, + inputs, output, tpt._0); ret T_fn_pair(lcx.ccx.tn, llfnty); } case (_) { // fall through } } - ret type_of(lcx.ccx, tpt._1); + ret type_of(lcx.ccx, sp, tpt._1); } @@ -1201,14 +1207,14 @@ fn llalign_of(TypeRef t) -> ValueRef { fn size_of(&@block_ctxt cx, &ty::t t) -> result { if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, t)) { - ret res(cx, llsize_of(type_of(cx.fcx.lcx.ccx, t))); + ret res(cx, llsize_of(type_of(cx.fcx.lcx.ccx, cx.sp, t))); } ret dynamic_size_of(cx, t); } fn align_of(&@block_ctxt cx, &ty::t t) -> result { if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, t)) { - ret res(cx, llalign_of(type_of(cx.fcx.lcx.ccx, t))); + ret res(cx, llalign_of(type_of(cx.fcx.lcx.ccx, cx.sp, t))); } ret dynamic_align_of(cx, t); } @@ -1243,7 +1249,7 @@ fn simplify_type(&@crate_ctxt ccx, &ty::t typ) -> ty::t { } // Computes the size of the data part of a non-dynamically-sized tag. -fn static_size_of_tag(&@crate_ctxt cx, &ty::t t) -> uint { +fn static_size_of_tag(&@crate_ctxt cx, &ast::span sp, &ty::t t) -> uint { if (ty::type_has_dynamic_size(cx.tcx, t)) { log_err "dynamically sized type passed to static_size_of_tag()"; fail; @@ -1277,7 +1283,7 @@ fn static_size_of_tag(&@crate_ctxt cx, &ty::t t) -> uint { tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty); // Here we possibly do a recursive call. - auto this_size = llsize_of_real(cx, type_of(cx, tup_ty)); + auto this_size = llsize_of_real(cx, type_of(cx, sp, tup_ty)); if (max_size < this_size) { max_size = this_size; @@ -1502,7 +1508,7 @@ fn GEP_tup_like(&@block_ctxt cx, &ty::t t, ret res(bcx, bumped); } - auto typ = T_ptr(type_of(bcx.fcx.lcx.ccx, s.target)); + auto typ = T_ptr(type_of(bcx.fcx.lcx.ccx, bcx.sp, s.target)); ret res(bcx, bcx.build.PointerCast(bumped, typ)); } @@ -1543,7 +1549,7 @@ fn GEP_tag(@block_ctxt cx, // the blob pointer isn't dynamically sized). let ValueRef llunionptr; if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, tup_ty)) { - auto llty = type_of(cx.fcx.lcx.ccx, tup_ty); + auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, tup_ty); llunionptr = cx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); } else { llunionptr = llblobptr; @@ -1555,7 +1561,7 @@ fn GEP_tag(@block_ctxt cx, // Cast the result to the appropriate type, if necessary. auto val; if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, elem_ty)) { - auto llelemty = type_of(rslt.bcx.fcx.lcx.ccx, elem_ty); + auto llelemty = type_of(rslt.bcx.fcx.lcx.ccx, cx.sp, elem_ty); val = rslt.bcx.build.PointerCast(rslt.val, T_ptr(llelemty)); } else { val = rslt.val; @@ -1581,7 +1587,7 @@ fn trans_malloc_boxed(&@block_ctxt cx, ty::t t) -> result { [ty::mk_int(cx.fcx.lcx.ccx.tcx), t]); auto box_ptr = ty::mk_imm_box(cx.fcx.lcx.ccx.tcx, t); auto sz = size_of(cx, boxed_body); - auto llty = type_of(cx.fcx.lcx.ccx, box_ptr); + auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, box_ptr); ret trans_raw_malloc(sz.bcx, llty, sz.val); } @@ -1790,7 +1796,7 @@ fn get_static_tydesc(&@block_ctxt cx, } case (none[@tydesc_info]) { cx.fcx.lcx.ccx.stats.n_static_tydescs += 1u; - auto info = declare_tydesc(cx.fcx.lcx, t, ty_params); + auto info = declare_tydesc(cx.fcx.lcx, cx.sp, t, ty_params); cx.fcx.lcx.ccx.tydescs.insert(t, info); ret info; } @@ -1798,7 +1804,7 @@ fn get_static_tydesc(&@block_ctxt cx, } // Generates the declaration for (but doesn't emit) a type descriptor. -fn declare_tydesc(&@local_ctxt cx, &ty::t t, +fn declare_tydesc(&@local_ctxt cx, &ast::span sp, &ty::t t, vec[uint] ty_params) -> @tydesc_info { log "+++ declare_tydesc " + ty::ty_to_str(cx.ccx.tcx, t); auto take_glue = declare_generic_glue(cx, t, T_glue_fn(cx.ccx.tn), @@ -1812,7 +1818,7 @@ fn declare_tydesc(&@local_ctxt cx, &ty::t t, auto llsize; auto llalign; if (!ty::type_has_dynamic_size(ccx.tcx, t)) { - auto llty = type_of(ccx, t); + auto llty = type_of(ccx, sp, t); llsize = llsize_of(llty); llalign = llalign_of(llty); } else { @@ -1866,12 +1872,12 @@ fn declare_generic_glue(&@local_ctxt cx, ret llfn; } -fn make_generic_glue(&@local_ctxt cx, +fn make_generic_glue(&@local_ctxt cx, &ast::span sp, &ty::t t, ValueRef llfn, &make_generic_glue_helper_fn helper, &vec[uint] ty_params) -> ValueRef { - auto fcx = new_fn_ctxt(cx, llfn); + auto fcx = new_fn_ctxt(cx, sp, llfn); llvm::LLVMSetLinkage(llfn, lib::llvm::LLVMInternalLinkage as llvm::Linkage); @@ -1887,7 +1893,7 @@ fn make_generic_glue(&@local_ctxt cx, if (ty::type_has_dynamic_size(cx.ccx.tcx, t)) { llty = T_ptr(T_i8()); } else { - llty = T_ptr(type_of(cx.ccx, t)); + llty = T_ptr(type_of(cx.ccx, sp, t)); } auto ty_param_count = vec::len[uint](ty_params); @@ -2347,7 +2353,8 @@ fn make_cmp_glue(&@block_ctxt cx, // i8[]. So we need to cast it to the proper type. if (!ty::type_has_dynamic_size(last_cx.fcx.lcx.ccx.tcx, t)) { - auto llelemty = T_ptr(type_of(last_cx.fcx.lcx.ccx, t)); + auto llelemty = T_ptr(type_of(last_cx.fcx.lcx.ccx, + last_cx.sp, t)); av = cx.build.PointerCast(av, llelemty); bv = cx.build.PointerCast(bv, llelemty); } @@ -2826,7 +2833,7 @@ fn iter_sequence_inner(&@block_ctxt cx, ValueRef src) -> result { auto llptrty; if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, elt_ty)) { - auto llty = type_of(cx.fcx.lcx.ccx, elt_ty); + auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, elt_ty); llptrty = T_ptr(llty); } else { llptrty = T_ptr(T_ptr(T_i8())); @@ -2863,7 +2870,7 @@ fn iter_sequence(@block_ctxt cx, if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, elt_ty)) { llunit_ty = T_i8(); } else { - llunit_ty = type_of(cx.fcx.lcx.ccx, elt_ty); + llunit_ty = type_of(cx.fcx.lcx.ccx, cx.sp, elt_ty); } auto bcx = cx; @@ -2933,7 +2940,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field, "take"); ti.take_glue = some[ValueRef](glue_fn); auto tg = make_take_glue; - make_generic_glue(lcx, ti.ty, glue_fn, + make_generic_glue(lcx, cx.sp, ti.ty, glue_fn, mgghf_single(tg), ti.ty_params); log #fmt("--- lazily_emit_tydesc_glue TAKE %s", @@ -2953,7 +2960,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field, "drop"); ti.drop_glue = some[ValueRef](glue_fn); auto dg = make_drop_glue; - make_generic_glue(lcx, ti.ty, glue_fn, + make_generic_glue(lcx, cx.sp, ti.ty, glue_fn, mgghf_single(dg), ti.ty_params); log #fmt("--- lazily_emit_tydesc_glue DROP %s", ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty)); @@ -2972,7 +2979,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field, T_cmp_glue_fn(lcx.ccx.tn), "cmp"); ti.cmp_glue = some[ValueRef](glue_fn); - make_generic_glue(lcx, ti.ty, glue_fn, + make_generic_glue(lcx, cx.sp, ti.ty, glue_fn, mgghf_cmp, ti.ty_params); log #fmt("--- lazily_emit_tydesc_glue CMP %s", ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty)); @@ -3024,7 +3031,7 @@ fn maybe_call_dtor(&@block_ctxt cx, ValueRef v) -> @block_ctxt { dtor_ptr = cx.build.Load(dtor_ptr); auto self_t = llvm::LLVMGetElementType(val_ty(v)); dtor_ptr = cx.build.BitCast(dtor_ptr, - T_ptr(T_dtor(cx.fcx.lcx.ccx, self_t))); + T_ptr(T_dtor(cx.fcx.lcx.ccx, cx.sp, self_t))); auto dtor_cx = new_sub_block_ctxt(cx, "dtor"); auto after_cx = new_sub_block_ctxt(cx, "after_dtor"); @@ -3286,8 +3293,8 @@ fn node_ann_type(&@crate_ctxt cx, &ast::ann a) -> ty::t { ret target_type(cx, ty::ann_to_monotype(cx.tcx, cx.node_types, a)); } -fn node_type(&@crate_ctxt cx, &ast::ann a) -> TypeRef { - ret type_of(cx, node_ann_type(cx, a)); +fn node_type(&@crate_ctxt cx, &ast::span sp, &ast::ann a) -> TypeRef { + ret type_of(cx, sp, node_ann_type(cx, a)); } fn trans_unary(&@block_ctxt cx, ast::unop op, @@ -3342,7 +3349,8 @@ fn trans_unary(&@block_ctxt cx, ast::unop op, // make tags work, since tags have a different LLVM type depending // on whether they're boxed or not. if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, e_ty)) { - auto llety = T_ptr(type_of(sub.bcx.fcx.lcx.ccx, e_ty)); + auto llety = T_ptr(type_of(sub.bcx.fcx.lcx.ccx, e.span, + e_ty)); body = sub.bcx.build.PointerCast(body, llety); } @@ -3538,7 +3546,7 @@ fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result { // different types depending on whether they're behind a box // or not. if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, mt.ty)) { - auto llty = type_of(cx.fcx.lcx.ccx, mt.ty); + auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, mt.ty); v1 = cx.build.PointerCast(body, T_ptr(llty)); } else { v1 = body; @@ -3731,7 +3739,8 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond, if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) { expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn); } else { - expr_llty = type_of(else_res.bcx.fcx.lcx.ccx, expr_ty); + expr_llty = type_of(else_res.bcx.fcx.lcx.ccx, elexpr.span, + expr_ty); if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, expr_ty)) { expr_llty = T_ptr(expr_llty); } @@ -3972,7 +3981,7 @@ fn trans_for_each(&@block_ctxt cx, // and pass it in as a first class fn-arg to the iterator. auto iter_body_llty = - type_of_fn_full(lcx.ccx, ast::proto_fn, + type_of_fn_full(lcx.ccx, cx.sp, ast::proto_fn, none[TypeRef], [rec(mode=ty::mo_alias, ty=decl_ty)], ty::mk_nil(lcx.ccx.tcx), 0u); @@ -3980,7 +3989,7 @@ fn trans_for_each(&@block_ctxt cx, let ValueRef lliterbody = decl_internal_fastcall_fn(lcx.ccx.llmod, s, iter_body_llty); - auto fcx = new_fn_ctxt(lcx, lliterbody); + auto fcx = new_fn_ctxt(lcx, cx.sp, lliterbody); auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs); @@ -4269,7 +4278,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr, if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) { expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn); } else { - expr_llty = type_of(cx.fcx.lcx.ccx, expr_ty); + expr_llty = type_of(cx.fcx.lcx.ccx, expr.span, expr_ty); if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, expr_ty)) { expr_llty = T_ptr(expr_llty); } @@ -4309,7 +4318,8 @@ fn trans_external_path(&@block_ctxt cx, &ast::def_id did, auto lcx = cx.fcx.lcx; auto name = creader::get_symbol(lcx.ccx.sess, did); auto v = get_extern_const(lcx.ccx.externs, lcx.ccx.llmod, - name, type_of_ty_param_count_and_ty(lcx, tpt)); + name, + type_of_ty_param_count_and_ty(lcx, cx.sp, tpt)); ret lval_val(cx, v); } @@ -4440,7 +4450,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, &ast::ann ann) -> lval_result { tag_ty)) { lltagty = T_opaque_tag(cx.fcx.lcx.ccx.tn); } else { - lltagty = type_of(cx.fcx.lcx.ccx, tag_ty); + lltagty = type_of(cx.fcx.lcx.ccx, p.span, tag_ty); } auto lltagptr = alloc_result.bcx.build. PointerCast(lltagblob, T_ptr(lltagty)); @@ -4566,7 +4576,7 @@ fn trans_index(&@block_ctxt cx, &ast::span sp, &@ast::expr base, elt = next_cx.build.GEP(body, [C_int(0), ix_val]); // We're crossing a box boundary here, so we may need to pointer cast. - auto llunitty = type_of(next_cx.fcx.lcx.ccx, unit_ty); + auto llunitty = type_of(next_cx.fcx.lcx.ccx, sp, unit_ty); elt = next_cx.build.PointerCast(elt, T_ptr(llunitty)); } @@ -4642,7 +4652,7 @@ fn trans_cast(&@block_ctxt cx, &@ast::expr e, &ast::ann ann) -> result { auto e_res = trans_expr(cx, e); auto llsrctype = val_ty(e_res.val); auto t = node_ann_type(cx.fcx.lcx.ccx, ann); - auto lldsttype = type_of(cx.fcx.lcx.ccx, t); + auto lldsttype = type_of(cx.fcx.lcx.ccx, e.span, t); if (!ty::type_is_fp(cx.fcx.lcx.ccx.tcx, t)) { // TODO: native-to-native casts if (ty::type_is_native(cx.fcx.lcx.ccx.tcx, @@ -4662,6 +4672,7 @@ fn trans_cast(&@block_ctxt cx, &@ast::expr e, &ast::ann ann) -> result { } fn trans_bind_thunk(&@local_ctxt cx, + &ast::span sp, &ty::t incoming_fty, &ty::t outgoing_fty, &vec[option::t[@ast::expr]] args, @@ -4672,16 +4683,17 @@ fn trans_bind_thunk(&@local_ctxt cx, // args forward into a call to outgoing_fty: let str s = mangle_name_by_seq(cx.ccx, cx.path, "thunk"); - let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx.ccx, incoming_fty)); + let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx.ccx, sp, + incoming_fty)); let ValueRef llthunk = decl_internal_fastcall_fn(cx.ccx.llmod, s, llthunk_ty); - auto fcx = new_fn_ctxt(cx, llthunk); + auto fcx = new_fn_ctxt(cx, sp, llthunk); auto bcx = new_top_block_ctxt(fcx); auto lltop = bcx.llbb; auto llclosure_ptr_ty = - type_of(cx.ccx, ty::mk_imm_box(cx.ccx.tcx, closure_ty)); + type_of(cx.ccx, sp, ty::mk_imm_box(cx.ccx.tcx, closure_ty)); auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ptr_ty); auto lltarget = GEP_tup_like(bcx, closure_ty, llclosure, @@ -4726,7 +4738,7 @@ fn trans_bind_thunk(&@local_ctxt cx, let int b = 0; let uint outgoing_arg_index = 0u; let vec[TypeRef] llout_arg_tys = - type_of_explicit_args(cx.ccx, outgoing_args); + type_of_explicit_args(cx.ccx, sp, outgoing_args); for (option::t[@ast::expr] arg in args) { @@ -4791,7 +4803,7 @@ fn trans_bind_thunk(&@local_ctxt cx, // Cast the outgoing function to the appropriate type (see the comments in // trans_bind below for why this is necessary). - auto lltargetty = type_of_fn(bcx.fcx.lcx.ccx, + auto lltargetty = type_of_fn(bcx.fcx.lcx.ccx, sp, ty::ty_fn_proto(bcx.fcx.lcx.ccx.tcx, outgoing_fty), outgoing_args, @@ -4850,7 +4862,7 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f, ret f_res.res; } else { auto bcx = f_res.res.bcx; - auto pair_t = node_type(cx.fcx.lcx.ccx, ann); + auto pair_t = node_type(cx.fcx.lcx.ccx, cx.sp, ann); auto pair_v = alloca(bcx, pair_t); // Translate the bound expressions. @@ -4919,7 +4931,7 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f, // specifically, we know how many type descriptors the outgoing // function has, which type_of() doesn't, as only we know which // item the function refers to. - auto llfnty = type_of_fn(bcx.fcx.lcx.ccx, + auto llfnty = type_of_fn(bcx.fcx.lcx.ccx, cx.sp, ty::ty_fn_proto(bcx.fcx.lcx.ccx.tcx, outgoing_fty), ty::ty_fn_args(bcx.fcx.lcx.ccx.tcx, outgoing_fty), ty::ty_fn_ret(bcx.fcx.lcx.ccx.tcx, outgoing_fty), @@ -4980,7 +4992,7 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f, let ty::t pair_ty = node_ann_type(cx.fcx.lcx.ccx, ann); let ValueRef llthunk = - trans_bind_thunk(cx.fcx.lcx, pair_ty, outgoing_fty, + trans_bind_thunk(cx.fcx.lcx, cx.sp, pair_ty, outgoing_fty, args, closure_ty, bound_tys, ty_param_count); @@ -5121,7 +5133,7 @@ fn trans_args(&@block_ctxt cx, // view, for the sake of making a type-compatible call. llargs += [cx.build.PointerCast(llretslot, - T_ptr(type_of(bcx.fcx.lcx.ccx, retty)))]; + T_ptr(type_of(bcx.fcx.lcx.ccx, bcx.sp, retty)))]; } else { llargs += [llretslot]; } @@ -5159,7 +5171,7 @@ fn trans_args(&@block_ctxt cx, // First we figure out the caller's view of the types of the arguments. // This will be needed if this is a generic call, because the callee has // to cast her view of the arguments to the caller's view. - auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, args); + auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, cx.sp, args); auto i = 0u; for (@ast::expr e in es) { @@ -5309,7 +5321,7 @@ fn trans_vec(&@block_ctxt cx, &vec[@ast::expr] args, auto vec_val = bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.new_vec, [bcx.fcx.lltaskptr, data_sz, C_null(T_ptr(T_tydesc(bcx.fcx.lcx.ccx.tn)))]); - auto llty = type_of(bcx.fcx.lcx.ccx, t); + auto llty = type_of(bcx.fcx.lcx.ccx, bcx.sp, t); vec_val = bcx.build.PointerCast(vec_val, llty); find_scope_cx(bcx).cleanups += @@ -5344,7 +5356,7 @@ fn trans_vec(&@block_ctxt cx, &vec[@ast::expr] args, auto dst_val; if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, unit_ty)) { - auto llunit_ty = type_of(cx.fcx.lcx.ccx, unit_ty); + auto llunit_ty = type_of(cx.fcx.lcx.ccx, bcx.sp, unit_ty); dst_val = bcx.build.PointerCast(dst_res.val, T_ptr(llunit_ty)); } else { dst_val = dst_res.val; @@ -5416,9 +5428,8 @@ fn trans_rec(&@block_ctxt cx, &vec[ast::field] fields, ret res(bcx, rec_val); } - - fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result { + *cx = rec(sp=e.span with *cx); alt (e.node) { case (ast::expr_lit(?lit, ?ann)) { ret res(cx, trans_lit(cx.fcx.lcx.ccx, *lit, ann)); @@ -5459,6 +5470,7 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result { } case (ast::expr_block(?blk, _)) { + *cx = rec(sp=blk.span with *cx); auto sub_cx = new_scope_block_ctxt(cx, "block-expr body"); auto next_cx = new_sub_block_ctxt(cx, "next"); auto sub = trans_block(sub_cx, blk); @@ -5472,6 +5484,7 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result { case (ast::expr_assign(?dst, ?src, ?ann)) { auto lhs_res = trans_lval(cx, dst); assert (lhs_res.is_mem); + *(lhs_res.res.bcx) = rec(sp=src.span with *(lhs_res.res.bcx)); auto rhs_res = trans_expr(lhs_res.res.bcx, src); auto t = node_ann_type(cx.fcx.lcx.ccx, ann); // FIXME: calculate copy init-ness in typestate. @@ -5483,6 +5496,7 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result { auto t = node_ann_type(cx.fcx.lcx.ccx, ann); auto lhs_res = trans_lval(cx, dst); assert (lhs_res.is_mem); + *(lhs_res.res.bcx) = rec(sp=src.span with *(lhs_res.res.bcx)); auto rhs_res = trans_expr(lhs_res.res.bcx, src); if (ty::type_is_sequence(cx.fcx.lcx.ccx.tcx, t)) { alt (op) { @@ -5773,7 +5787,8 @@ fn trans_put(&@block_ctxt cx, &option::t[@ast::expr] e) -> result { auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, cx.fcx.lcx.ccx.node_types, x); auto arg = rec(mode=ty::mo_alias, ty=e_ty); - auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, [arg]); + auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, + x.span, [arg]); auto r = trans_arg_expr(bcx, arg, arg_tys.(0), x); bcx = r.bcx; llargs += [r.val]; @@ -5886,14 +5901,14 @@ fn trans_port(&@block_ctxt cx, &ast::ann ann) -> result { } } - auto llunit_ty = type_of(cx.fcx.lcx.ccx, unit_ty); + auto llunit_ty = type_of(cx.fcx.lcx.ccx, cx.sp, unit_ty); auto bcx = cx; auto unit_sz = size_of(bcx, unit_ty); bcx = unit_sz.bcx; auto port_raw_val = bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.new_port, [bcx.fcx.lltaskptr, unit_sz.val]); - auto llty = type_of(cx.fcx.lcx.ccx, t); + auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, t); auto port_val = bcx.build.PointerCast(port_raw_val, llty); auto dropref = clean(bind drop_ty(_, port_val, t)); find_scope_cx(bcx).cleanups += [dropref]; @@ -5912,7 +5927,7 @@ fn trans_chan(&@block_ctxt cx, &@ast::expr e, &ast::ann ann) -> result { [bcx.fcx.lltaskptr, prt_val]); auto chan_ty = node_ann_type(bcx.fcx.lcx.ccx, ann); - auto chan_llty = type_of(bcx.fcx.lcx.ccx, chan_ty); + auto chan_llty = type_of(bcx.fcx.lcx.ccx, e.span, chan_ty); auto chan_val = bcx.build.PointerCast(chan_raw_val, chan_llty); auto dropref = clean(bind drop_ty(_, chan_val, chan_ty)); find_scope_cx(bcx).cleanups += [dropref]; @@ -6029,7 +6044,7 @@ fn zero_alloca(&@block_ctxt cx, ValueRef llptr, ty::t t) -> result { bcx = call_bzero(llalign.bcx, llptr, llsz.val, llalign.val).bcx; } else { - auto llty = type_of(bcx.fcx.lcx.ccx, t); + auto llty = type_of(bcx.fcx.lcx.ccx, cx.sp, t); auto null = lib::llvm::llvm::LLVMConstNull(llty); bcx.build.Store(null, llptr); } @@ -6037,6 +6052,7 @@ fn zero_alloca(&@block_ctxt cx, ValueRef llptr, ty::t t) -> result { } fn trans_stmt(&@block_ctxt cx, &ast::stmt s) -> result { + *cx = rec(sp=s.span with *cx); auto bcx = cx; alt (s.node) { case (ast::stmt_expr(?e,_)) { @@ -6082,6 +6098,7 @@ fn new_block_ctxt(&@fn_ctxt cx, &block_parent parent, parent=parent, kind=kind, mutable cleanups=cleanups, + sp=cx.sp, fcx=cx); } @@ -6110,7 +6127,8 @@ fn new_sub_block_ctxt(&@block_ctxt bcx, &str n) -> @block_ctxt { fn new_raw_block_ctxt(&@fn_ctxt fcx, BasicBlockRef llbb) -> @block_ctxt { let vec[cleanup] cleanups = []; ret @rec(llbb=llbb, build=new_builder(llbb), parent=parent_none, - kind=NON_SCOPE_BLOCK, mutable cleanups=cleanups, fcx=fcx); + kind=NON_SCOPE_BLOCK, mutable cleanups=cleanups, sp=fcx.sp, + fcx=fcx); } @@ -6160,6 +6178,7 @@ fn llallocas_block_ctxt(&@fn_ctxt fcx) -> @block_ctxt { parent=parent_none, kind=SCOPE_BLOCK, mutable cleanups=cleanups, + sp=fcx.sp, fcx=fcx); } @@ -6176,7 +6195,7 @@ fn alloc_ty(&@block_ctxt cx, &ty::t t) -> result { cx.fcx.llallocas = n.bcx.llbb; val = array_alloca(cx, T_i8(), n.val); } else { - val = alloca(cx, type_of(cx.fcx.lcx.ccx, t)); + val = alloca(cx, type_of(cx.fcx.lcx.ccx, cx.sp, t)); } // NB: since we've pushed all size calculations in this // function up to the alloca block, we actually return the @@ -6198,6 +6217,7 @@ fn trans_block(&@block_ctxt cx, &ast::block b) -> result { auto bcx = cx; for each (@ast::local local in block_locals(b)) { + *bcx = rec(sp=local_rhs_span(local, cx.sp) with *bcx); bcx = alloc_local(bcx, local).bcx; } auto r = res(bcx, C_nil()); @@ -6299,7 +6319,7 @@ fn mk_standard_basic_blocks(ValueRef llfn) -> // - new_fn_ctxt // - trans_args -fn new_fn_ctxt(@local_ctxt cx, +fn new_fn_ctxt(@local_ctxt cx, &ast::span sp, ValueRef llfndecl) -> @fn_ctxt { let ValueRef llretptr = llvm::LLVMGetParam(llfndecl, 0u); @@ -6331,6 +6351,7 @@ fn new_fn_ctxt(@local_ctxt cx, llupvars=llupvars, mutable lltydescs=vec::empty[ValueRef](), derived_tydescs=derived_tydescs, + sp=sp, lcx=cx); } @@ -6415,7 +6436,7 @@ fn copy_args_to_allocas(@fn_ctxt fcx, let uint arg_n = 0u; for (ast::arg aarg in args) { if (aarg.mode != ast::alias) { - auto arg_t = type_of_arg(bcx.fcx.lcx, arg_tys.(arg_n)); + auto arg_t = type_of_arg(bcx.fcx.lcx, fcx.sp, arg_tys.(arg_n)); auto a = alloca(bcx, arg_t); auto argval = bcx.fcx.llargs.get(aarg.id); bcx.build.Store(argval, a); @@ -6509,7 +6530,7 @@ fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, self_vt llself) { // fields pointer to the appropriate LLVM type. If not, just leave it as // i8 *. if (!ty::type_has_dynamic_size(fcx.lcx.ccx.tcx, fields_tup_ty)) { - auto llfields_ty = type_of(fcx.lcx.ccx, fields_tup_ty); + auto llfields_ty = type_of(fcx.lcx.ccx, fcx.sp, fields_tup_ty); obj_fields = vi2p(bcx, obj_fields, T_ptr(llfields_ty)); } else { obj_fields = vi2p(bcx, obj_fields, T_ptr(T_i8())); @@ -6546,12 +6567,12 @@ fn finish_fn(&@fn_ctxt fcx, BasicBlockRef lltop) { new_builder(fcx.llderivedtydescs).Br(lltop); } -fn trans_fn(@local_ctxt cx, &ast::_fn f, ast::def_id fid, +fn trans_fn(@local_ctxt cx, &ast::span sp, &ast::_fn f, ast::def_id fid, option::t[tup(TypeRef, ty::t)] ty_self, &vec[ast::ty_param] ty_params, &ast::ann ann) { auto llfndecl = cx.ccx.item_ids.get(fid); - auto fcx = new_fn_ctxt(cx, llfndecl); + auto fcx = new_fn_ctxt(cx, sp, llfndecl); create_llargs_for_fn_args(fcx, f.proto, ty_self, ret_ty_of_fn(cx.ccx, ann), f.decl.inputs, ty_params); @@ -6611,7 +6632,7 @@ fn trans_vtbl(@local_ctxt cx, auto llfnty = T_nil(); alt (ty::struct(cx.ccx.tcx, node_ann_type(cx.ccx, m.node.ann))) { case (ty::ty_fn(?proto, ?inputs, ?output)) { - llfnty = type_of_fn_full(cx.ccx, proto, + llfnty = type_of_fn_full(cx.ccx, m.span, proto, some[TypeRef](llself_ty), inputs, output, vec::len[ast::ty_param](ty_params)); @@ -6625,7 +6646,7 @@ fn trans_vtbl(@local_ctxt cx, cx.ccx.item_ids.insert(m.node.id, llfn); cx.ccx.item_symbols.insert(m.node.id, s); - trans_fn(mcx, m.node.meth, m.node.id, + trans_fn(mcx, m.span, m.node.meth, m.node.id, some[tup(TypeRef, ty::t)](tup(llself_ty, self_ty)), ty_params, m.node.ann); methods += [llfn]; @@ -6647,21 +6668,21 @@ fn trans_dtor(@local_ctxt cx, &vec[ast::ty_param] ty_params, &@ast::method dtor) -> ValueRef { - auto llfnty = T_dtor(cx.ccx, llself_ty); + auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty); let @local_ctxt dcx = extend_path(cx, "drop"); let str s = mangle_name_by_seq(dcx.ccx, dcx.path, "drop"); let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty); cx.ccx.item_ids.insert(dtor.node.id, llfn); cx.ccx.item_symbols.insert(dtor.node.id, s); - trans_fn(dcx, dtor.node.meth, dtor.node.id, + trans_fn(dcx, dtor.span, dtor.node.meth, dtor.node.id, some[tup(TypeRef, ty::t)](tup(llself_ty, self_ty)), ty_params, dtor.node.ann); ret llfn; } -fn trans_obj(@local_ctxt cx, &ast::_obj ob, ast::def_id oid, +fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid, &vec[ast::ty_param] ty_params, &ast::ann ann) { auto ccx = cx.ccx; auto llctor_decl = ccx.item_ids.get(oid); @@ -6672,7 +6693,7 @@ fn trans_obj(@local_ctxt cx, &ast::_obj ob, ast::def_id oid, fn_args += [rec(mode=ast::alias, ty=f.ty, ident=f.ident, id=f.id)]; } - auto fcx = new_fn_ctxt(cx, llctor_decl); + auto fcx = new_fn_ctxt(cx, sp, llctor_decl); create_llargs_for_fn_args(fcx, ast::proto_fn, none[tup(TypeRef, ty::t)], ret_ty_of_fn(ccx, ann), @@ -6685,7 +6706,7 @@ fn trans_obj(@local_ctxt cx, &ast::_obj ob, ast::def_id oid, auto lltop = bcx.llbb; auto self_ty = ret_ty_of_fn(ccx, ann); - auto llself_ty = type_of(ccx, self_ty); + auto llself_ty = type_of(ccx, sp, self_ty); auto pair = bcx.fcx.llretptr; auto vtbl = trans_vtbl(cx, llself_ty, self_ty, ob, ty_params); @@ -6819,7 +6840,7 @@ fn trans_tag_variant(@local_ctxt cx, ast::def_id tag_id, assert (cx.ccx.item_ids.contains_key(variant.node.id)); let ValueRef llfndecl = cx.ccx.item_ids.get(variant.node.id); - auto fcx = new_fn_ctxt(cx, llfndecl); + auto fcx = new_fn_ctxt(cx, variant.span, llfndecl); create_llargs_for_fn_args(fcx, ast::proto_fn, none[tup(TypeRef, ty::t)], @@ -6915,13 +6936,14 @@ fn trans_item(@local_ctxt cx, &ast::item item) { alt (item.node) { case (ast::item_fn(?name, ?f, ?tps, ?fid, ?ann)) { auto sub_cx = extend_path(cx, name); - trans_fn(sub_cx, f, fid, none[tup(TypeRef, ty::t)], tps, ann); + trans_fn(sub_cx, item.span, f, fid, none[tup(TypeRef, ty::t)], + tps, ann); } case (ast::item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { auto sub_cx = @rec(obj_typarams=tps, obj_fields=ob.fields with *extend_path(cx, name)); - trans_obj(sub_cx, ob, oid.ctor, tps, ann); + trans_obj(sub_cx, item.span, ob, oid.ctor, tps, ann); } case (ast::item_mod(?name, ?m, _)) { auto sub_cx = @rec(path = cx.path + [name], @@ -6958,7 +6980,7 @@ fn get_pair_fn_ty(TypeRef llpairty) -> TypeRef { ret llvm::LLVMGetElementType(pair_tys.(0)); } -fn decl_fn_and_pair(&@crate_ctxt ccx, +fn decl_fn_and_pair(&@crate_ctxt ccx, &ast::span sp, vec[str] path, str flav, vec[ast::ty_param] ty_params, @@ -6969,7 +6991,7 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, auto llpairty; alt (ty::struct(ccx.tcx, node_ann_type(ccx, ann))) { case (ty::ty_fn(?proto, ?inputs, ?output)) { - llfty = type_of_fn(ccx, proto, inputs, output, + llfty = type_of_fn(ccx, sp, proto, inputs, output, vec::len[ast::ty_param](ty_params)); llpairty = T_fn_pair(ccx.tn, llfty); } @@ -7024,17 +7046,18 @@ fn native_fn_ty_param_count(&@crate_ctxt cx, &ast::def_id id) -> uint { ret count; } -fn native_fn_wrapper_type(&@crate_ctxt cx, uint ty_param_count, ty::t x) - -> TypeRef { +fn native_fn_wrapper_type(&@crate_ctxt cx, &ast::span sp, uint ty_param_count, + ty::t x) -> TypeRef { alt (ty::struct(cx.tcx, x)) { case (ty::ty_native_fn(?abi, ?args, ?out)) { - ret type_of_fn(cx, ast::proto_fn, args, out, ty_param_count); + ret type_of_fn(cx, sp, ast::proto_fn, args, out, ty_param_count); } } fail; } fn decl_native_fn_and_pair(&@crate_ctxt ccx, + &ast::span sp, vec[str] path, str name, &ast::ann ann, @@ -7043,7 +7066,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, // Declare the wrapper. auto t = node_ann_type(ccx, ann); - auto wrapper_type = native_fn_wrapper_type(ccx, num_ty_param, t); + auto wrapper_type = native_fn_wrapper_type(ccx, sp, num_ty_param, t); let str s = mangle_name_by_seq(ccx, path, "wrapper"); let ValueRef wrapper_fn = decl_internal_fastcall_fn(ccx.llmod, s, wrapper_type); @@ -7055,7 +7078,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, register_fn_pair(ccx, ps, wrapper_pair_type, wrapper_fn, id); // Build the wrapper. - auto fcx = new_fn_ctxt(new_local_ctxt(ccx), wrapper_fn); + auto fcx = new_fn_ctxt(new_local_ctxt(ccx), sp, wrapper_fn); auto bcx = new_top_block_ctxt(fcx); auto lltop = bcx.llbb; @@ -7064,7 +7087,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, auto fn_type = node_ann_type(ccx, ann); // NB: has no type params auto abi = ty::ty_fn_abi(ccx.tcx, fn_type); - auto llfnty = type_of_native_fn(ccx, abi, + auto llfnty = type_of_native_fn(ccx, sp, abi, ty::ty_fn_args(ccx.tcx, fn_type), ty::ty_fn_ret(ccx.tcx, fn_type), num_ty_param); @@ -7127,7 +7150,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, if (mode == ty::mo_val) { if (ty::type_is_integral(cx.fcx.lcx.ccx.tcx, t)) { auto lldsttype = T_int(); - auto llsrctype = type_of(cx.fcx.lcx.ccx, t); + auto llsrctype = type_of(cx.fcx.lcx.ccx, cx.sp, t); if (llvm::LLVMGetIntTypeWidth(lldsttype) > llvm::LLVMGetIntTypeWidth(llsrctype)) { ret cx.build.ZExtOrBitCast(v, T_int()); @@ -7154,7 +7177,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, auto llnativefnty = T_fn(call_arg_tys, - type_of(bcx.fcx.lcx.ccx, + type_of(bcx.fcx.lcx.ccx, bcx.sp, ty::ty_fn_ret(bcx.fcx.lcx.ccx.tcx, fn_type))); auto llnativefn = get_extern_fn(bcx.fcx.lcx.ccx.externs, @@ -7270,7 +7293,8 @@ fn collect_native_item(&@crate_ctxt ccx, @walk_ctxt wcx, case (ast::native_item_fn(?name, _, _, _, ?fid, ?ann)) { ccx.native_items.insert(fid, i); if (!ccx.obj_methods.contains_key(fid)) { - decl_native_fn_and_pair(ccx, wcx.path, name, ann, fid); + decl_native_fn_and_pair(ccx, i.span, wcx.path, + name, ann, fid); } } case (ast::native_item_ty(_, ?tid)) { @@ -7285,7 +7309,7 @@ fn collect_item_1(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item i) { alt (i.node) { case (ast::item_const(?name, _, _, ?cid, ?ann)) { auto typ = node_ann_type(ccx, ann); - auto g = llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), + auto g = llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, i.span, typ), str::buf(ccx.names.next(name))); llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage); @@ -7315,12 +7339,13 @@ fn collect_item_2(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item i) { case (ast::item_fn(?name, ?f, ?tps, ?fid, ?ann)) { ccx.items.insert(fid, i); if (!ccx.obj_methods.contains_key(fid)) { - decl_fn_and_pair(ccx, wcx.path, "fn", tps, ann, fid); + decl_fn_and_pair(ccx, i.span, wcx.path, "fn", tps, ann, fid); } } case (ast::item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { ccx.items.insert(oid.ctor, i); - decl_fn_and_pair(ccx, wcx.path, "obj_ctor", tps, ann, oid.ctor); + decl_fn_and_pair(ccx, i.span, wcx.path, + "obj_ctor", tps, ann, oid.ctor); for (@ast::method m in ob.methods) { ccx.obj_methods.insert(m.node.id, ()); } @@ -7351,7 +7376,8 @@ fn collect_tag_ctor(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item i) { case (ast::item_tag(_, ?variants, ?tps, _, _)) { for (ast::variant variant in variants) { if (vec::len[ast::variant_arg](variant.node.args) != 0u) { - decl_fn_and_pair(ccx, wcx.path + [variant.node.name], + decl_fn_and_pair(ccx, i.span, + wcx.path + [variant.node.name], "tag", tps, variant.node.ann, variant.node.id); } @@ -7677,7 +7703,7 @@ fn vec_p1_adjusted(&@block_ctxt bcx, ValueRef v, ret bcx.build.GEP(vec_p0(bcx, v), [len]); } -fn trans_vec_append_glue(@local_ctxt cx) { +fn trans_vec_append_glue(@local_ctxt cx, &ast::span sp) { auto llfn = cx.ccx.glues.vec_append_glue; @@ -7707,6 +7733,7 @@ fn trans_vec_append_glue(@local_ctxt cx) { llupvars=new_def_hash[ValueRef](), mutable lltydescs=vec::empty[ValueRef](), derived_tydescs=derived_tydescs, + sp=sp, lcx=cx); auto bcx = new_top_block_ctxt(fcx); @@ -7978,7 +8005,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate, &ty::ctxt tcx, collect_tag_ctors(ccx, crate); trans_constants(ccx, crate); trans_mod(cx, crate.node.module); - trans_vec_append_glue(cx); + trans_vec_append_glue(cx, crate.span); auto crate_map = create_crate_map(ccx); if (!sess.get_opts().shared) { trans_main_fn(cx, crate_ptr, crate_map); diff --git a/src/test/compile-fail/vector-no-ann-2.rs b/src/test/compile-fail/vector-no-ann-2.rs new file mode 100644 index 0000000000000..c21d49e34dc4b --- /dev/null +++ b/src/test/compile-fail/vector-no-ann-2.rs @@ -0,0 +1,5 @@ +// error-pattern:3:24:3:25 +fn main() -> () { + let @vec[uint] foo = @[]; +} +// this checks that span_err gets used diff --git a/src/test/compile-fail/vector-no-ann.rs b/src/test/compile-fail/vector-no-ann.rs new file mode 100644 index 0000000000000..9b303e607fa1c --- /dev/null +++ b/src/test/compile-fail/vector-no-ann.rs @@ -0,0 +1,5 @@ +// error-pattern:3:13:3:14 +fn main() -> () { + auto foo = []; +} +// this checks that span_err gets used From c4f9ab9c6b8f3f86722a98738ff27e6b032ab7d1 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:38:11 -0700 Subject: [PATCH 07/10] Add a set_all function in bitv that's the inverse of clear --- src/lib/bitv.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/bitv.rs b/src/lib/bitv.rs index 708cc621868b0..5ea8e456684c7 100644 --- a/src/lib/bitv.rs +++ b/src/lib/bitv.rs @@ -5,7 +5,6 @@ // FIXME: Almost all the functions in this module should be state fns, but the // effect system isn't currently working correctly. - state type t = rec(vec[mutable uint] storage, uint nbits); // FIXME: this should be a constant once they work @@ -114,6 +113,12 @@ fn clear(&t v) { } } +fn set_all(&t v) { + for each (uint i in _uint::range(0u, v.nbits)) { + set(v, i, true); + } +} + fn invert(&t v) { for each (uint i in uint::range(0u, vec::len(v.storage))) { v.storage.(i) = ~v.storage.(i); From c37b70af6bb564bcf38dd26f82f8efc9c0074d37 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:38:54 -0700 Subject: [PATCH 08/10] Add visit_fn_pre and visit_fn_post fields to visitors Added visit_fn_pre and visit_fn_post fields that get applied to both regular functions and methods. --- src/comp/middle/walk.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/comp/middle/walk.rs b/src/comp/middle/walk.rs index 972356c628e8e..27e3542736827 100644 --- a/src/comp/middle/walk.rs +++ b/src/comp/middle/walk.rs @@ -31,7 +31,9 @@ type ast_visitor = fn (&@ast::expr e) visit_expr_pre, fn (&@ast::expr e) visit_expr_post, fn (&@ast::ty t) visit_ty_pre, - fn (&@ast::ty t) visit_ty_post); + fn (&@ast::ty t) visit_ty_post, + fn (&ast::_fn f, &ast::def_id d_id) visit_fn_pre, + fn (&ast::_fn f, &ast::def_id d_id) visit_fn_post); fn walk_crate(&ast_visitor v, &ast::crate c) { if (!v.keep_going()) { ret; } @@ -91,8 +93,8 @@ fn walk_item(&ast_visitor v, @ast::item i) { walk_ty(v, t); walk_expr(v, e); } - case (ast::item_fn(_, ?f, _, _, _)) { - walk_fn(v, f); + case (ast::item_fn(_, ?f, _, ?d, _)) { + walk_fn(v, f, d); } case (ast::item_mod(_, ?m, _)) { walk_mod(v, m); @@ -116,13 +118,13 @@ 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); + walk_fn(v, m.node.meth, m.node.id); v.visit_method_post(m); } alt (ob.dtor) { case (none[@ast::method]) {} case (some[@ast::method](?m)) { - walk_fn(v, m.node.meth); + walk_fn(v, m.node.meth, m.node.id); } } } @@ -227,10 +229,12 @@ 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) { +fn walk_fn(&ast_visitor v, &ast::_fn f, &ast::def_id d) { if (!v.keep_going()) { ret; } + v.visit_fn_pre(f, d); walk_fn_decl(v, f.decl); walk_block(v, f.body); + v.visit_fn_post(f, d); } fn walk_block(&ast_visitor v, &ast::block b) { @@ -455,6 +459,7 @@ 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::def_id d) { } fn default_visitor() -> ast_visitor { @@ -472,6 +477,7 @@ fn default_visitor() -> ast_visitor { auto d_visit_decl = def_visit_decl; auto d_visit_expr = def_visit_expr; auto d_visit_ty = def_visit_ty; + auto d_visit_fn = def_visit_fn; ret rec(keep_going = d_keep_going, want_crate_directives = d_want_crate_directives, @@ -498,7 +504,9 @@ fn default_visitor() -> ast_visitor { visit_expr_pre = d_visit_expr, visit_expr_post = d_visit_expr, visit_ty_pre = d_visit_ty, - visit_ty_post = d_visit_ty); + visit_ty_post = d_visit_ty, + visit_fn_pre = d_visit_fn, + visit_fn_post = d_visit_fn); } // From 941b6eca634c9a7d8ba10e4339abd289adbaaeca Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 15:43:05 -0700 Subject: [PATCH 09/10] Rewrite tstate.annotate to use walk instead of fold and various other tidying in typestate --- src/comp/middle/tstate/ann.rs | 36 +- src/comp/middle/tstate/annotate.rs | 452 +++--------------- src/comp/middle/tstate/auxiliary.rs | 239 ++++----- src/comp/middle/tstate/bitvectors.rs | 10 +- src/comp/middle/tstate/ck.rs | 125 +++-- src/comp/middle/tstate/collect_locals.rs | 25 +- src/comp/middle/tstate/pre_post_conditions.rs | 224 ++++----- src/comp/middle/tstate/states.rs | 392 ++++++++------- src/lib/bitv.rs | 2 +- 9 files changed, 621 insertions(+), 884 deletions(-) diff --git a/src/comp/middle/tstate/ann.rs b/src/comp/middle/tstate/ann.rs index 3e8c8e34a58c5..a62829f3a1082 100644 --- a/src/comp/middle/tstate/ann.rs +++ b/src/comp/middle/tstate/ann.rs @@ -20,13 +20,13 @@ type poststate = bitv::t; /* 1 means "this variable is definitely initialized" initialized" */ /* named thus so as not to confuse with prestate and poststate */ -type pre_and_post = rec(precond precondition, postcond postcondition); +type pre_and_post = @rec(precond precondition, postcond postcondition); /* FIXME: once it's implemented: */ // : ((*.precondition).nbits == (*.postcondition).nbits); type pre_and_post_state = rec(prestate prestate, poststate poststate); -type ts_ann = rec(pre_and_post conditions, pre_and_post_state states); +type ts_ann = @rec(pre_and_post conditions, pre_and_post_state states); fn true_precond(uint num_vars) -> precond { be bitv::create(num_vars, false); @@ -49,18 +49,18 @@ fn false_postcond(uint num_vars) -> postcond { } fn empty_pre_post(uint num_vars) -> pre_and_post { - ret(rec(precondition=empty_prestate(num_vars), - postcondition=empty_poststate(num_vars))); + ret(@rec(precondition=empty_prestate(num_vars), + postcondition=empty_poststate(num_vars))); } fn empty_states(uint num_vars) -> pre_and_post_state { ret(rec(prestate=true_precond(num_vars), - poststate=true_postcond(num_vars))); + poststate=true_postcond(num_vars))); } fn empty_ann(uint num_vars) -> ts_ann { - ret(rec(conditions=empty_pre_post(num_vars), - states=empty_states(num_vars))); + ret(@rec(conditions=empty_pre_post(num_vars), + states=empty_states(num_vars))); } fn get_pre(&pre_and_post p) -> precond { @@ -111,25 +111,25 @@ fn set_in_poststate(uint i, &pre_and_post_state s) -> bool { // Sets all the bits in a's precondition to equal the // corresponding bit in p's precondition. -fn set_precondition(@ts_ann a, &precond p) -> () { +fn set_precondition(ts_ann a, &precond p) -> () { bitv::copy(a.conditions.precondition, p); } // Sets all the bits in a's postcondition to equal the // corresponding bit in p's postcondition. -fn set_postcondition(@ts_ann a, &postcond p) -> () { +fn set_postcondition(ts_ann a, &postcond p) -> () { bitv::copy(a.conditions.postcondition, p); } // Sets all the bits in a's prestate to equal the // corresponding bit in p's prestate. -fn set_prestate(@ts_ann a, &prestate p) -> bool { +fn set_prestate(ts_ann a, &prestate p) -> bool { ret bitv::copy(a.states.prestate, p); } // Sets all the bits in a's postcondition to equal the // corresponding bit in p's postcondition. -fn set_poststate(@ts_ann a, &poststate p) -> bool { +fn set_poststate(ts_ann a, &poststate p) -> bool { ret bitv::copy(a.states.poststate, p); } @@ -150,6 +150,16 @@ fn relax_prestate(uint i, &prestate p) -> bool { ret was_set; } +// Clears all the bits in p +fn clear(&precond p) -> () { + bitv::clear(p); +} + +// Sets all the bits in p +fn set(&precond p) -> () { + bitv::set_all(p); +} + fn ann_precond(&ts_ann a) -> precond { ret a.conditions.precondition; } @@ -163,8 +173,8 @@ fn ann_poststate(&ts_ann a) -> poststate { } fn pp_clone(&pre_and_post p) -> pre_and_post { - ret rec(precondition=clone(p.precondition), - postcondition=clone(p.postcondition)); + ret @rec(precondition=clone(p.precondition), + postcondition=clone(p.postcondition)); } fn clone(prestate p) -> prestate { diff --git a/src/comp/middle/tstate/annotate.rs b/src/comp/middle/tstate/annotate.rs index 92e6accdbec33..f126930386441 100644 --- a/src/comp/middle/tstate/annotate.rs +++ b/src/comp/middle/tstate/annotate.rs @@ -4,7 +4,6 @@ import std::option::some; import std::option::none; import front::ast; - import front::ast::ident; import front::ast::def_id; import front::ast::ann; @@ -76,417 +75,104 @@ import front::ast::method; import middle::fold; import middle::fold::respan; -import middle::fold::new_identity_fold; -import middle::fold::fold_crate; -import middle::fold::fold_item; -import middle::fold::fold_method; +import middle::ty::expr_ann; import util::common::uistr; import util::common::span; import util::common::new_str_hash; +import util::common::log_expr_err; +import util::common::log_block_err; +import util::common::log_item_err; +import util::common::log_stmt_err; +import util::common::log_expr; +import util::common::log_block; +import util::common::log_stmt; import middle::tstate::aux::fn_info; import middle::tstate::aux::fn_info_map; import middle::tstate::aux::num_locals; -import middle::tstate::aux::init_ann; -import middle::tstate::aux::init_blank_ann; import middle::tstate::aux::get_fn_info; +import middle::tstate::aux::crate_ctxt; +import middle::tstate::ann::empty_ann; -fn item_fn_anns(&fn_info_map fm, &span sp, ident i, &_fn f, - vec[ty_param] ty_params, def_id id, ann a) -> @item { - - assert (fm.contains_key(id)); - auto f_info = fm.get(id); - - log(i + " has " + uistr(num_locals(f_info)) + " local vars"); - - auto fld0 = new_identity_fold[fn_info](); - - fld0 = @rec(fold_ann = bind init_ann(_,_) - with *fld0); - - ret fold_item[fn_info] - (f_info, fld0, @respan(sp, item_fn(i, f, ty_params, id, a))); -} - -/* FIXME: rewrite this with walk instead of fold */ - -/* This is painstakingly written as an explicit recursion b/c the - standard ast.fold doesn't traverse in the correct order: - consider - fn foo() { - fn bar() { - auto x = 5; - log(x); - } - } - With fold, first bar() would be processed and its subexps would - correctly be annotated with length-1 bit vectors. - But then, the process would be repeated with (fn bar()...) as - a subexp of foo, which has 0 local variables -- so then - the body of bar() would be incorrectly annotated with length-0 bit - vectors. */ -fn annotate_exprs(&fn_info_map fm, &vec[@expr] es) -> vec[@expr] { - fn one(fn_info_map fm, &@expr e) -> @expr { - ret annotate_expr(fm, e); - } - auto f = bind one(fm,_); - ret vec::map[@expr, @expr](f, es); -} -fn annotate_elts(&fn_info_map fm, &vec[elt] es) -> vec[elt] { - fn one(fn_info_map fm, &elt e) -> elt { - ret rec(mut=e.mut, - expr=annotate_expr(fm, e.expr)); - } - auto f = bind one(fm,_); - ret vec::map[elt, elt](f, es); -} -fn annotate_fields(&fn_info_map fm, &vec[field] fs) -> vec[field] { - fn one(fn_info_map fm, &field f) -> field { - ret rec(mut=f.mut, - ident=f.ident, - expr=annotate_expr(fm, f.expr)); - } - auto f = bind one(fm,_); - ret vec::map[field, field](f, fs); +fn collect_ids_expr(&@expr e, @vec[uint] res) -> () { + vec::push(*res, (expr_ann(e)).id); } -fn annotate_option_exp(&fn_info_map fm, &option::t[@expr] o) - -> option::t[@expr] { - fn one(fn_info_map fm, &@expr e) -> @expr { - ret annotate_expr(fm, e); - } - auto f = bind one(fm,_); - ret option::map[@expr, @expr](f, o); -} -fn annotate_option_exprs(&fn_info_map fm, &vec[option::t[@expr]] es) - -> vec[option::t[@expr]] { - fn one(fn_info_map fm, &option::t[@expr] o) -> option::t[@expr] { - ret annotate_option_exp(fm, o); - } - auto f = bind one(fm,_); - ret vec::map[option::t[@expr], option::t[@expr]](f, es); -} -fn annotate_decl(&fn_info_map fm, &@decl d) -> @decl { - auto d1 = d.node; - alt (d.node) { - case (decl_local(?l)) { - alt(l.init) { - case (some[initializer](?init)) { - let option::t[initializer] an_i = - some[initializer] - (rec(expr=annotate_expr(fm, init.expr) - with init)); - let @local new_l = @rec(init=an_i with *l); - d1 = decl_local(new_l); - } - case (_) { /* do nothing */ } - } - } - case (decl_item(?item)) { - d1 = decl_item(annotate_item(fm, item)); - } - } - ret @respan(d.span, d1); +fn collect_ids_block(&block b, @vec[uint] res) -> () { + vec::push(*res, b.node.a.id); } -fn annotate_alts(&fn_info_map fm, &vec[arm] alts) -> vec[arm] { - fn one(fn_info_map fm, &arm a) -> arm { - ret rec(pat=a.pat, - block=annotate_block(fm, a.block)); - } - auto f = bind one(fm,_); - ret vec::map[arm, arm](f, alts); -} -fn annotate_expr(&fn_info_map fm, &@expr e) -> @expr { - auto e1 = e.node; - alt (e.node) { - case (expr_vec(?es, ?m, ?a)) { - e1 = expr_vec(annotate_exprs(fm, es), m, a); - } - case (expr_tup(?es, ?a)) { - e1 = expr_tup(annotate_elts(fm, es), a); - } - case (expr_rec(?fs, ?maybe_e, ?a)) { - e1 = expr_rec(annotate_fields(fm, fs), - annotate_option_exp(fm, maybe_e), a); - } - case (expr_call(?e, ?es, ?a)) { - e1 = expr_call(annotate_expr(fm, e), - annotate_exprs(fm, es), a); - } - case (expr_self_method(_,_)) { - // no change - } - case (expr_bind(?e, ?maybe_es, ?a)) { - e1 = expr_bind(annotate_expr(fm, e), - annotate_option_exprs(fm, maybe_es), - a); - } - case (expr_spawn(?s, ?maybe_s, ?e, ?es, ?a)) { - e1 = expr_spawn(s, maybe_s, annotate_expr(fm, e), - annotate_exprs(fm, es), a); - } - case (expr_binary(?bop, ?w, ?x, ?a)) { - e1 = expr_binary(bop, annotate_expr(fm, w), - annotate_expr(fm, x), a); - } - case (expr_unary(?uop, ?w, ?a)) { - e1 = expr_unary(uop, annotate_expr(fm, w), a); - } - case (expr_lit(_,_)) { - /* no change */ - } - case (expr_cast(?e,?t,?a)) { - e1 = expr_cast(annotate_expr(fm, e), t, a); - } - case (expr_if(?e, ?b, ?maybe_e, ?a)) { - e1 = expr_if(annotate_expr(fm, e), - annotate_block(fm, b), - annotate_option_exp(fm, maybe_e), a); - } - case (expr_while(?e, ?b, ?a)) { - e1 = expr_while(annotate_expr(fm, e), - annotate_block(fm, b), a); - } - case (expr_for(?d, ?e, ?b, ?a)) { - e1 = expr_for(annotate_decl(fm, d), - annotate_expr(fm, e), - annotate_block(fm, b), a); - } - case (expr_for_each(?d, ?e, ?b, ?a)) { - e1 = expr_for_each(annotate_decl(fm, d), - annotate_expr(fm, e), - annotate_block(fm, b), a); - } - case (expr_do_while(?b, ?e, ?a)) { - e1 = expr_do_while(annotate_block(fm, b), - annotate_expr(fm, e), a); - } - case (expr_alt(?e, ?alts, ?a)) { - e1 = expr_alt(annotate_expr(fm, e), - annotate_alts(fm, alts), a); - } - case (expr_block(?b, ?a)) { - e1 = expr_block(annotate_block(fm, b), a); - } - case (expr_assign(?l, ?r, ?a)) { - e1 = expr_assign(annotate_expr(fm, l), annotate_expr(fm, r), a); - } - case (expr_assign_op(?bop, ?l, ?r, ?a)) { - e1 = expr_assign_op(bop, - annotate_expr(fm, l), annotate_expr(fm, r), a); - } - case (expr_send(?l, ?r, ?a)) { - e1 = expr_send(annotate_expr(fm, l), - annotate_expr(fm, r), a); - } - case (expr_recv(?l, ?r, ?a)) { - e1 = expr_recv(annotate_expr(fm, l), - annotate_expr(fm, r), a); - } - case (expr_field(?e, ?i, ?a)) { - e1 = expr_field(annotate_expr(fm, e), - i, a); - } - case (expr_index(?e, ?sub, ?a)) { - e1 = expr_index(annotate_expr(fm, e), - annotate_expr(fm, sub), a); - } - case (expr_path(_,_)) { - /* no change */ - } - case (expr_ext(?p, ?es, ?s_opt, ?e, ?a)) { - e1 = expr_ext(p, annotate_exprs(fm, es), - s_opt, - annotate_expr(fm, e), a); - } - /* no change, next 3 cases */ - case (expr_fail(_)) { } - case (expr_break(_)) { } - case (expr_cont(_)) { } - case (expr_ret(?maybe_e, ?a)) { - e1 = expr_ret(annotate_option_exp(fm, maybe_e), a); - } - case (expr_put(?maybe_e, ?a)) { - e1 = expr_put(annotate_option_exp(fm, maybe_e), a); - } - case (expr_be(?e, ?a)) { - e1 = expr_be(annotate_expr(fm, e), a); - } - case (expr_log(?n, ?e, ?a)) { - e1 = expr_log(n, annotate_expr(fm, e), a); - } - case (expr_assert(?e, ?a)) { - e1 = expr_assert(annotate_expr(fm, e), a); - } - case (expr_check(?e, ?a)) { - e1 = expr_check(annotate_expr(fm, e), a); - } - case (expr_port(_)) { /* no change */ } - case (expr_chan(?e, ?a)) { - e1 = expr_chan(annotate_expr(fm, e), a); +fn collect_ids_stmt(&@stmt s, @vec[uint] res) -> () { + alt (s.node) { + case (stmt_decl(_,?a)) { + log("node_id " + uistr(a.id)); + log_stmt(*s); + + vec::push(*res, a.id); + } + case (stmt_expr(_,?a)) { + log("node_id " + uistr(a.id)); + log_stmt(*s); + + vec::push(*res, a.id); } + case (_) {} } - ret @respan(e.span, e1); } -fn annotate_stmt(&fn_info_map fm, &@stmt s) -> @stmt { - alt (s.node) { - case (stmt_decl(?d, ?a)) { - ret @respan(s.span, stmt_decl(annotate_decl(fm, d), a)); - } - case (stmt_expr(?e, ?a)) { - ret @respan(s.span, stmt_expr(annotate_expr(fm, e), a)); +fn collect_ids_decl(&@decl d, @vec[uint] res) -> () { + alt (d.node) { + case (decl_local(?l)) { + vec::push(*res, l.ann.id); } + case (_) {} } } -fn annotate_block(&fn_info_map fm, &block b) -> block { - let vec[@stmt] new_stmts = []; - - for (@stmt s in b.node.stmts) { - auto new_s = annotate_stmt(fm, s); - vec::push[@stmt](new_stmts, new_s); - } - fn ann_e(fn_info_map fm, &@expr e) -> @expr { - ret annotate_expr(fm, e); - } - auto f = bind ann_e(fm,_); - - auto new_e = option::map[@expr, @expr](f, b.node.expr); - ret respan(b.span, - rec(stmts=new_stmts, expr=new_e with b.node)); -} -fn annotate_fn(&fn_info_map fm, &_fn f) -> _fn { - // subexps have *already* been annotated based on - // f's number-of-locals - ret rec(body=annotate_block(fm, f.body) with f); -} -fn annotate_mod(&fn_info_map fm, &_mod m) -> _mod { - let vec[@item] new_items = []; - - for (@item i in m.items) { - auto new_i = annotate_item(fm, i); - vec::push[@item](new_items, new_i); - } - ret rec(items=new_items with m); -} -fn annotate_method(&fn_info_map fm, &@method m) -> @method { - auto f_info = get_fn_info(fm, m.node.id); - auto fld0 = new_identity_fold[fn_info](); - fld0 = @rec(fold_ann = bind init_ann(_,_) - with *fld0); - auto outer = fold_method[fn_info](f_info, fld0, m); - auto new_fn = annotate_fn(fm, outer.node.meth); - ret @respan(m.span, - rec(meth=new_fn with m.node)); +fn node_ids_in_fn(&_fn f, &def_id d, @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, d); } -fn annotate_obj(&fn_info_map fm, &_obj o) -> _obj { - fn one(fn_info_map fm, &@method m) -> @method { - ret annotate_method(fm, m); +fn init_vecs(&crate_ctxt ccx, @vec[uint] node_ids, uint len) -> () { + for (uint i in *node_ids) { + log(uistr(i) + " |-> " + uistr(len)); + ccx.node_anns.insert(i, empty_ann(len)); } - auto f = bind one(fm,_); - auto new_methods = vec::map[@method, @method](f, o.methods); - auto new_dtor = option::map[@method, @method](f, o.dtor); - ret rec(methods=new_methods, dtor=new_dtor with o); } - -// Only annotates the components of the item recursively. -fn annotate_item_inner(&fn_info_map fm, &@item item) -> @item { - alt (item.node) { - /* FIXME can't skip this case -- exprs contain blocks contain stmts, - which contain decls */ - case (item_const(_,_,_,_,_)) { - // this has already been annotated by annotate_item - ret item; - } - case (item_fn(?ident, ?ff, ?tps, ?id, ?ann)) { - ret @respan(item.span, - item_fn(ident, annotate_fn(fm, ff), tps, id, ann)); - } - case (item_mod(?ident, ?mm, ?id)) { - ret @respan(item.span, - item_mod(ident, annotate_mod(fm, mm), id)); - } - case (item_native_mod(?ident, ?mm, ?id)) { - ret item; - } - case (item_ty(_,_,_,_,_)) { - ret item; - } - case (item_tag(_,_,_,_,_)) { - ret item; - } - case (item_obj(?ident, ?ob, ?tps, ?odid, ?ann)) { - ret @respan(item.span, - item_obj(ident, annotate_obj(fm, ob), tps, odid, ann)); - } - } +fn visit_fn(&crate_ctxt ccx, uint num_locals, &_fn f, &def_id d) -> () { + + let vec[uint] node_ids_ = []; + let @vec[uint] node_ids = @node_ids_; + node_ids_in_fn(f, d, node_ids); + init_vecs(ccx, node_ids, num_locals); } -fn annotate_item(&fn_info_map fm, &@item item) -> @item { - // Using a fold, recursively set all anns in this item - // to be blank. - // *Then*, call annotate_item recursively to do the right - // thing for any nested items inside this one. - - alt (item.node) { - case (item_const(_,_,_,_,_)) { - auto fld0 = new_identity_fold[()](); - fld0 = @rec(fold_ann = bind init_blank_ann(_,_) - with *fld0); - ret fold_item[()]((), fld0, item); - } - case (item_fn(?i,?ff,?tps,?id,?ann)) { - auto f_info = get_fn_info(fm, id); - auto fld0 = new_identity_fold[fn_info](); - fld0 = @rec(fold_ann = bind init_ann(_,_) - with *fld0); - auto outer = fold_item[fn_info](f_info, fld0, item); - // now recurse into any nested items - ret annotate_item_inner(fm, outer); - } - case (item_mod(?i, ?mm, ?id)) { - auto fld0 = new_identity_fold[()](); - fld0 = @rec(fold_ann = bind init_blank_ann(_,_) - with *fld0); - auto outer = fold_item[()]((), fld0, item); - ret annotate_item_inner(fm, outer); - } - case (item_native_mod(?i, ?nm, ?id)) { - ret item; - } - case (item_ty(_,_,_,_,_)) { - ret item; - } - case (item_tag(_,_,_,_,_)) { - ret item; - } - case (item_obj(?i,?ob,?tps,?odid,?ann)) { - auto fld0 = new_identity_fold[()](); - fld0 = @rec(fold_ann = bind init_blank_ann(_,_) - with *fld0); - auto outer = fold_item[()]((), fld0, item); - ret annotate_item_inner(fm, outer); - } - } +fn annotate_in_fn(&crate_ctxt ccx, &_fn f, &def_id f_id) -> () { + auto f_info = get_fn_info(ccx, f_id); + visit_fn(ccx, num_locals(f_info), f, f_id); } -fn annotate_module(&fn_info_map fm, &_mod module) -> _mod { - let vec[@item] new_items = []; - - for (@item i in module.items) { - auto new_item = annotate_item(fm, i); - vec::push[@item](new_items, new_item); - } - - ret rec(items = new_items with module); +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, _, _) + with do_ann); + walk::walk_crate(do_ann, crate); } -fn annotate_crate(&fn_info_map fm, &@crate crate) -> @crate { - ret @respan(crate.span, - rec(module = annotate_module(fm, crate.node.module) - with crate.node)); -} +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs index dbe411b0b66e7..2e656e45ceb19 100644 --- a/src/comp/middle/tstate/auxiliary.rs +++ b/src/comp/middle/tstate/auxiliary.rs @@ -37,6 +37,7 @@ import util::common; import util::common::span; import util::common::log_block; import util::common::new_def_hash; +import util::common::new_uint_hash; import util::common::log_expr_err; import util::common::uistr; @@ -157,6 +158,10 @@ fn print_idents(vec[ident] idents) -> () { type var_info = tup(uint, ident); type fn_info = rec(@std::map::hashmap[def_id, var_info] vars, controlflow cf); + +/* mapping from node ID to typestate annotation */ +type node_ann_table = @std::map::hashmap[uint, ts_ann]; + /* mapping from function name to fn_info map */ type fn_info_map = @std::map::hashmap[def_id, fn_info]; @@ -167,176 +172,187 @@ type fn_ctxt = rec(fn_info enclosing, type crate_ctxt = rec(ty::ctxt tcx, ty::node_type_table node_types, + node_ann_table node_anns, fn_info_map fm); -fn get_fn_info(fn_info_map fm, def_id did) -> fn_info { - assert (fm.contains_key(did)); - ret fm.get(did); +fn get_fn_info(&crate_ctxt ccx, def_id did) -> fn_info { + assert (ccx.fm.contains_key(did)); + ret ccx.fm.get(did); } /********* utils ********/ - -fn ann_to_ts_ann(ann a, uint nv) -> @ts_ann { - alt (ann_to_ts_ann_fail(a)) { - case (none[@ts_ann]) { ret @empty_ann(nv); } - case (some[@ts_ann](?t)) { ret t; } - } -} - - -fn ann_to_ts_ann_fail(ann a) -> option::t[@ts_ann] { ret a.ts; } - -fn ann_to_ts_ann_strict(ann a) -> @ts_ann { - alt (ann_to_ts_ann_fail(a)) { - case (none[@ts_ann]) { - log("ann_to_ts_ann_strict: didn't expect none here"); +fn ann_to_ts_ann(&crate_ctxt ccx, &ann a) -> ts_ann { + alt (ccx.node_anns.find(a.id)) { + case (none[ts_ann]) { + log_err ("ann_to_ts_ann: no ts_ann for node_id " + + uistr(a.id)); fail; } - case (some[@ts_ann](?t)) { ret t; } + case (some[ts_ann](?t)) { ret t; } } } -fn ann_to_poststate(ann a) -> poststate { - ret (ann_to_ts_ann_strict(a)).states.poststate; +fn ann_to_poststate(&crate_ctxt ccx, ann a) -> poststate { + log "ann_to_poststate"; + ret (ann_to_ts_ann(ccx, a)).states.poststate; } -fn stmt_to_ann(&stmt s) -> option::t[@ts_ann] { +fn stmt_to_ann(&crate_ctxt ccx, &stmt s) -> ts_ann { + log "stmt_to_ann"; alt (s.node) { case (stmt_decl(_,?a)) { - ret ann_to_ts_ann_fail(a); + ret ann_to_ts_ann(ccx, a); } case (stmt_expr(_,?a)) { - ret ann_to_ts_ann_fail(a); + ret ann_to_ts_ann(ccx, a); } case (stmt_crate_directive(_)) { - ret none[@ts_ann]; + log_err "expecting an annotated statement here"; + fail; } } } -fn stmt_to_ann_strict(&stmt s) -> @ts_ann { - alt (stmt_to_ann(s)) { - case (none[@ts_ann]) { - log_err("stmt_to_ann_strict: didn't expect none here"); - fail; - } - case (some[@ts_ann](?a)) { ret a; } - } -} - /* fails if e has no annotation */ -fn expr_states(@expr e) -> pre_and_post_state { - ret (ann_to_ts_ann_strict(expr_ann(e)).states); +fn expr_states(&crate_ctxt ccx, @expr e) -> pre_and_post_state { + log "expr_states"; + ret (ann_to_ts_ann(ccx, expr_ann(e)).states); } /* fails if e has no annotation */ -fn expr_pp(@expr e) -> pre_and_post { - ret (ann_to_ts_ann_strict(expr_ann(e)).conditions); +fn expr_pp(&crate_ctxt ccx, @expr e) -> pre_and_post { + log "expr_pp"; + ret (ann_to_ts_ann(ccx, expr_ann(e)).conditions); } -fn stmt_pp(&stmt s) -> pre_and_post { - ret (stmt_to_ann_strict(s).conditions); +fn stmt_pp(&crate_ctxt ccx, &stmt s) -> pre_and_post { + ret (stmt_to_ann(ccx, s).conditions); } /* fails if b has no annotation */ -fn block_pp(&block b) -> pre_and_post { - ret (ann_to_ts_ann_strict(b.node.a).conditions); +fn block_pp(&crate_ctxt ccx, &block b) -> pre_and_post { + log "block_pp"; + ret (ann_to_ts_ann(ccx, b.node.a).conditions); } -fn block_states(&block b) -> pre_and_post_state { - ret (ann_to_ts_ann_strict(b.node.a).states); +fn clear_pp(pre_and_post pp) { + ann::clear(pp.precondition); + ann::clear(pp.postcondition); } -fn stmt_states(&stmt s, uint nv) -> pre_and_post_state { - alt (stmt_to_ann(s)) { - case (none[@ts_ann]) { - ret empty_states(nv); - } - case (some[@ts_ann](?a)) { - ret a.states; - } - } +fn clear_precond(&crate_ctxt ccx, &ann a) { + auto pp = ann_to_ts_ann(ccx, a); + ann::clear(pp.conditions.precondition); +} + +fn block_states(&crate_ctxt ccx, &block b) -> pre_and_post_state { + log "block_states"; + ret (ann_to_ts_ann(ccx, b.node.a).states); } -fn expr_precond(@expr e) -> precond { - ret (expr_pp(e)).precondition; +fn stmt_states(&crate_ctxt ccx, &stmt s) -> pre_and_post_state { + ret (stmt_to_ann(ccx, s)).states; } -fn expr_postcond(@expr e) -> postcond { - ret (expr_pp(e)).postcondition; +fn expr_precond(&crate_ctxt ccx, @expr e) -> precond { + ret (expr_pp(ccx, e)).precondition; } -fn expr_prestate(@expr e) -> prestate { - ret (expr_states(e)).prestate; +fn expr_postcond(&crate_ctxt ccx, @expr e) -> postcond { + ret (expr_pp(ccx, e)).postcondition; } -fn expr_poststate(@expr e) -> poststate { - ret (expr_states(e)).poststate; +fn expr_prestate(&crate_ctxt ccx, @expr e) -> prestate { + ret (expr_states(ccx, e)).prestate; } -fn stmt_precond(&stmt s) -> precond { - ret (stmt_pp(s)).precondition; +fn expr_poststate(&crate_ctxt ccx, @expr e) -> poststate { + ret (expr_states(ccx, e)).poststate; } -fn stmt_postcond(&stmt s) -> postcond { - ret (stmt_pp(s)).postcondition; +fn stmt_precond(&crate_ctxt ccx, &stmt s) -> precond { + ret (stmt_pp(ccx, s)).precondition; +} + +fn stmt_postcond(&crate_ctxt ccx, &stmt s) -> postcond { + ret (stmt_pp(ccx, s)).postcondition; } fn states_to_poststate(&pre_and_post_state ss) -> poststate { ret ss.poststate; } -fn stmt_prestate(&stmt s, uint nv) -> prestate { - ret (stmt_states(s, nv)).prestate; +fn stmt_prestate(&crate_ctxt ccx, &stmt s) -> prestate { + ret (stmt_states(ccx, s)).prestate; } -fn stmt_poststate(&stmt s, uint nv) -> poststate { - ret (stmt_states(s, nv)).poststate; +fn stmt_poststate(&crate_ctxt ccx, &stmt s) -> poststate { + ret (stmt_states(ccx, s)).poststate; } -fn block_postcond(&block b) -> postcond { - ret (block_pp(b)).postcondition; +fn block_postcond(&crate_ctxt ccx, &block b) -> postcond { + ret (block_pp(ccx, b)).postcondition; } -fn block_poststate(&block b) -> poststate { - ret (block_states(b)).poststate; +fn block_poststate(&crate_ctxt ccx, &block b) -> poststate { + ret (block_states(ccx, b)).poststate; } -/* returns a new annotation where the pre_and_post is p */ -fn with_pp(ann a, pre_and_post p) -> ann { - ret rec(id=a.id, ty=a.ty, tps=a.tps, - ts=some[@ts_ann](@rec(conditions=p, - states=empty_states(pps_len(p))))); +/* sets the pre_and_post for an ann */ +fn with_pp(&crate_ctxt ccx, &ann a, pre_and_post p) { + ccx.node_anns.insert(a.id, @rec(conditions=p, + states=empty_states(pps_len(p)))); } -fn set_prestate_ann(&ann a, &prestate pre) -> bool { - ret set_prestate(ann_to_ts_ann_strict(a), pre); +fn set_prestate_ann(&crate_ctxt ccx, &ann a, &prestate pre) -> bool { + log "set_prestate_ann"; + ret set_prestate(ann_to_ts_ann(ccx, a), pre); } -fn extend_prestate_ann(&ann a, &prestate pre) -> bool { - ret extend_prestate(ann_to_ts_ann_strict(a).states.prestate, pre); +fn extend_prestate_ann(&crate_ctxt ccx, &ann a, &prestate pre) -> bool { + log "extend_prestate_ann"; + ret extend_prestate(ann_to_ts_ann(ccx, a).states.prestate, pre); } -fn set_poststate_ann(&ann a, &poststate post) -> bool { - ret set_poststate(ann_to_ts_ann_strict(a), post); +fn set_poststate_ann(&crate_ctxt ccx, &ann a, &poststate post) -> bool { + log "set_poststate_ann"; + ret set_poststate(ann_to_ts_ann(ccx, a), post); } -fn extend_poststate_ann(&ann a, &poststate post) -> bool { - ret extend_poststate(ann_to_ts_ann_strict(a).states.poststate, post); +fn extend_poststate_ann(&crate_ctxt ccx, &ann a, &poststate post) -> bool { + log "extend_poststate_ann"; + ret extend_poststate(ann_to_ts_ann(ccx, a).states.poststate, post); } -fn set_pre_and_post(&ann a, &pre_and_post pp) -> () { - auto t = ann_to_ts_ann_strict(a); - set_precondition(t, pp.precondition); - set_postcondition(t, pp.postcondition); +fn set_pre_and_post(&crate_ctxt ccx, &ann a, + &precond pre, &postcond post) -> () { + log "set_pre_and_post"; + auto t = ann_to_ts_ann(ccx, a); + set_precondition(t, pre); + set_postcondition(t, post); } -fn pure_exp(&ann a, &prestate p) -> bool { +fn copy_pre_post(&crate_ctxt ccx, &ann a, &@expr sub) -> () { + log "set_pre_and_post"; + auto p = expr_pp(ccx, sub); + auto t = ann_to_ts_ann(ccx, a); + set_precondition(t, p.precondition); + set_postcondition(t, p.postcondition); +} + + +/* sets all bits to *1* */ +fn set_postcond_false(&crate_ctxt ccx, &ann a) { + auto p = ann_to_ts_ann(ccx, a); + ann::set(p.conditions.postcondition); +} + +fn pure_exp(&crate_ctxt ccx, &ann a, &prestate p) -> bool { auto changed = false; - changed = extend_prestate_ann(a, p) || changed; - changed = extend_poststate_ann(a, p) || changed; + changed = extend_prestate_ann(ccx, a, p) || changed; + changed = extend_poststate_ann(ccx, a, p) || changed; ret changed; } @@ -354,31 +370,14 @@ fn fixed_point_states(&fn_ctxt fcx, } } -fn init_ann(&fn_info fi, &ann a) -> ann { - ret rec(id=a.id, ty=a.ty, tps=a.tps, - ts=some[@ts_ann](@empty_ann(num_locals(fi)))); -} - -fn init_blank_ann(&() ignore, &ann a) -> ann { - ret rec(id=a.id, ty=a.ty, tps=a.tps, ts=some[@ts_ann](@empty_ann(0u))); -} - -fn init_block(&fn_info fi, &span sp, &block_ b) -> block { - log("init_block:"); - log_block(respan(sp, b)); - - auto fld0 = new_identity_fold[fn_info](); - - fld0 = @rec(fold_ann = bind init_ann(_,_) with *fld0); - ret fold_block[fn_info](fi, fld0, respan(sp, b)); -} - fn num_locals(fn_info m) -> uint { ret m.vars.size(); } fn new_crate_ctxt(ty::node_type_table nt, ty::ctxt cx) -> crate_ctxt { - ret rec(tcx=cx, node_types=nt, fm=@new_def_hash[fn_info]()); + ret rec(tcx=cx, node_types=nt, + node_anns=@new_uint_hash[ts_ann](), + fm=@new_def_hash[fn_info]()); } fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow { @@ -395,9 +394,15 @@ fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow { fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow { auto f = expr_ann(e).id; alt (ccx.tcx.def_map.find(f)) { - case (some[def](def_fn(?d))) { ret controlflow_def_id(ccx, d); } - case (some[def](def_obj_field(?d))) { ret controlflow_def_id(ccx, d); } - case (_) { ret return; } + case (some[def](def_fn(?d))) { + ret controlflow_def_id(ccx, d); + } + case (some[def](def_obj_field(?d))) { + ret controlflow_def_id(ccx, d); + } + case (_) { + ret return; + } } } diff --git a/src/comp/middle/tstate/bitvectors.rs b/src/comp/middle/tstate/bitvectors.rs index a0b9e5a3ece45..aa379e072af7d 100644 --- a/src/comp/middle/tstate/bitvectors.rs +++ b/src/comp/middle/tstate/bitvectors.rs @@ -12,8 +12,8 @@ import aux::fn_ctxt; import aux::fn_info; import aux::log_bitv; import aux::num_locals; -import aux::ann_to_ts_ann_strict; +import tstate::aux::ann_to_ts_ann; import tstate::ann::pre_and_post; import tstate::ann::precond; import tstate::ann::postcond; @@ -48,7 +48,7 @@ fn seq_preconds(fn_info enclosing, vec[pre_and_post] pps) -> precond { let uint num_vars = num_locals(enclosing); if (sz >= 1u) { - auto first = pps.(0); + auto first = pps.(0); assert (pps_len(first) == num_vars); let precond rest = seq_preconds(enclosing, slice[pre_and_post](pps, 1u, sz)); @@ -115,9 +115,10 @@ 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; - ret set_in_postcond(i, (ann_to_ts_ann_strict(a)).conditions); + ret set_in_postcond(i, (ann_to_ts_ann(fcx.ccx, a)).conditions); } fn declare_var(&fn_info enclosing, def_id id, prestate pre) @@ -130,8 +131,9 @@ 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; - ret set_in_poststate(i, (ann_to_ts_ann_strict(a)).states); + ret set_in_poststate(i, (ann_to_ts_ann(fcx.ccx, a)).states); } diff --git a/src/comp/middle/tstate/ck.rs b/src/comp/middle/tstate/ck.rs index f9e8416a32251..5de793d64b04f 100644 --- a/src/comp/middle/tstate/ck.rs +++ b/src/comp/middle/tstate/ck.rs @@ -56,6 +56,8 @@ import aux::fixed_point_states; import aux::bitv_to_str; import util::common::ty_to_str; +import util::common::log_stmt_err; +import aux::log_bitv_err; import bitvectors::promises; import annotate::annotate_crate; @@ -64,51 +66,45 @@ import pre_post_conditions::check_item_fn; import states::find_pre_post_state_fn; fn check_states_expr(&fn_ctxt fcx, @expr e) -> () { - let precond prec = expr_precond(e); - let prestate pres = expr_prestate(e); - - if (!implies(pres, prec)) { - auto s = ""; - s += ("Unsatisfied precondition constraint for expression:\n"); - s += util::common::expr_to_str(e); - s += ("Precondition: "); - s += bitv_to_str(fcx.enclosing, prec); - s += ("Prestate: "); - s += bitv_to_str(fcx.enclosing, pres); - fcx.ccx.tcx.sess.span_err(e.span, s); - } + let precond prec = expr_precond(fcx.ccx, e); + let prestate pres = expr_prestate(fcx.ccx, e); + + if (!implies(pres, prec)) { + auto s = ""; + s += ("Unsatisfied precondition constraint for expression:\n"); + s += util::common::expr_to_str(e); + s += ("Precondition: "); + s += bitv_to_str(fcx.enclosing, prec); + s += ("Prestate: "); + s += bitv_to_str(fcx.enclosing, pres); + fcx.ccx.tcx.sess.span_err(e.span, s); + } } fn check_states_stmt(&fn_ctxt fcx, &stmt s) -> () { - alt (stmt_to_ann(s)) { - case (none[@ts_ann]) { - ret; - } - case (some[@ts_ann](?a)) { - let precond prec = ann_precond(*a); - let prestate pres = ann_prestate(*a); - - /* - log("check_states_stmt:"); - log_stmt(s); - log("prec = "); - log_bitv(enclosing, prec); - log("pres = "); - log_bitv(enclosing, pres); - */ - - if (!implies(pres, prec)) { - auto ss = ""; - ss += ("Unsatisfied precondition constraint for statement:\n"); - ss += util::common::stmt_to_str(s); - ss += ("Precondition: "); - ss += bitv_to_str(fcx.enclosing, prec); - ss += ("Prestate: "); - ss += bitv_to_str(fcx.enclosing, pres); - fcx.ccx.tcx.sess.span_err(s.span, ss); - } + auto a = stmt_to_ann(fcx.ccx, s); + let precond prec = ann_precond(a); + let prestate pres = ann_prestate(a); + + /* + log_err("check_states_stmt:"); + log_stmt_err(s); + log_err("prec = "); + log_bitv_err(fcx.enclosing, prec); + log_err("pres = "); + log_bitv_err(fcx.enclosing, pres); + */ + + if (!implies(pres, prec)) { + auto ss = ""; + ss += ("Unsatisfied precondition constraint for statement:\n"); + ss += util::common::stmt_to_str(s); + ss += ("Precondition: "); + ss += bitv_to_str(fcx.enclosing, prec); + ss += ("Prestate: "); + ss += bitv_to_str(fcx.enclosing, pres); + fcx.ccx.tcx.sess.span_err(s.span, ss); } - } } fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) -> () { @@ -116,33 +112,30 @@ fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) -> () { auto nv = num_locals(enclosing); auto post = @empty_poststate(nv); - fn do_one_(fn_ctxt fcx, &@stmt s, @poststate post, uint nv) -> () { + fn do_one_(fn_ctxt fcx, &@stmt s, @poststate post) -> () { check_states_stmt(fcx, *s); - *post = stmt_poststate(*s, nv); + *post = stmt_poststate(fcx.ccx, *s); } - auto do_one = bind do_one_(fcx, _, post, nv); + auto do_one = bind do_one_(fcx, _, post); - vec::map[@stmt, ()](do_one, f.body.node.stmts); - fn do_inner_(fn_ctxt fcx, &@expr e, @poststate post) -> () { - check_states_expr(fcx, e); - *post = expr_poststate(e); - } - auto do_inner = bind do_inner_(fcx, _, post); - option::map[@expr, ()](do_inner, f.body.node.expr); + vec::map[@stmt, ()](do_one, f.body.node.stmts); + fn do_inner_(fn_ctxt fcx, &@expr e, @poststate post) -> () { + check_states_expr(fcx, e); + *post = expr_poststate(fcx.ccx, e); + } + auto do_inner = bind do_inner_(fcx, _, post); + option::map[@expr, ()](do_inner, f.body.node.expr); - /* Finally, check that the return value is initialized */ - if (f.proto == ast::proto_fn - && ! promises(*post, fcx.id, enclosing) - && ! type_is_nil(fcx.ccx.tcx, - ret_ty_of_fn(fcx.ccx.node_types, fcx.ccx.tcx, a)) ) { - /* FIXME: make this an error, not warning, once I finish implementing - ! annotations */ - /* fcx.ccx.tcx.sess.span_err(f.body.span, "Function " + - fcx.name + " may not return. Its declared return type is " - + util.common.ty_to_str(*f.decl.output)); */ - fcx.ccx.tcx.sess.span_warn(f.body.span, "not all control paths " + - "return a value"); + /* Finally, check that the return value is initialized */ + if (f.proto == ast::proto_fn + && ! promises(*post, fcx.id, enclosing) + && ! type_is_nil(fcx.ccx.tcx, + ret_ty_of_fn(fcx.ccx.node_types, fcx.ccx.tcx, a)) ) { + /* FIXME: call span_err, not span_warn, once I finish implementing + ! annotations */ + fcx.ccx.tcx.sess.span_warn(f.body.span, "In function " + fcx.name + + ", not all control paths return a value"); fcx.ccx.tcx.sess.span_note(f.decl.output.span, "see declared return type of '" + ty_to_str(*f.decl.output) + "'"); @@ -202,15 +195,15 @@ fn check_crate(ty::node_type_table nt, ty::ctxt cx, @crate crate) -> @crate { /* Build the global map from function id to var-to-bit-num-map */ mk_f_to_fn_info(ccx, crate); - /* Add a blank ts_ann to every statement (and expression) */ - auto with_anns = annotate_crate(ccx.fm, crate); + /* Add a blank ts_ann for every statement (and expression) */ + annotate_crate(ccx, *crate); /* Compute the pre and postcondition for every subexpression */ auto fld = new_identity_fold[crate_ctxt](); fld = @rec(fold_item_fn = bind check_item_fn(_,_,_,_,_,_,_) with *fld); auto with_pre_postconditions = - fold_crate[crate_ctxt](ccx, fld, with_anns); + fold_crate[crate_ctxt](ccx, fld, crate); auto fld1 = new_identity_fold[crate_ctxt](); diff --git a/src/comp/middle/tstate/collect_locals.rs b/src/comp/middle/tstate/collect_locals.rs index 29f73a149c786..9f99986009633 100644 --- a/src/comp/middle/tstate/collect_locals.rs +++ b/src/comp/middle/tstate/collect_locals.rs @@ -31,22 +31,28 @@ import aux::var_info; import aux::crate_ctxt; import util::common::new_def_hash; +import util::common::uistr; 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, &@local loc) -> () { - log("collect_local: pushing " + loc.ident); - _vec::push[tup(ident, def_id)](*vars, tup(loc.ident, loc.id)); +fn collect_local(&@vec[tup(ident, def_id)] 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)); + } + case (_) { ret; } + } } -fn find_locals(_fn f) -> @vec[tup(ident,def_id)] { +fn find_locals(_fn f, def_id d) -> @vec[tup(ident,def_id)] { auto res = @vec::alloc[tup(ident,def_id)](0u); auto visitor = walk::default_visitor(); visitor = rec(visit_decl_pre=bind collect_local(res,_) with visitor); - walk_fn(visitor, f); + walk_fn(visitor, f, d); ret res; } @@ -69,7 +75,7 @@ fn mk_fn_info(_fn f, def_id f_id, ident f_name) -> fn_info { /* ignore args, which we know are initialized; just collect locally declared vars */ - let @vec[tup(ident,def_id)] locals = find_locals(f); + let @vec[tup(ident,def_id)] locals = find_locals(f, f_id); // log (uistr(vec::len[tup(ident, def_id)](locals)) + " locals"); for (tup(ident,def_id) p in *locals) { next = add_var(p._1, p._0, next, res); @@ -78,6 +84,9 @@ fn mk_fn_info(_fn f, def_id f_id, ident f_name) -> fn_info { we can safely use the function's name itself for this purpose */ add_var(f_id, f_name, next, res); + log(f_name + " has " + uistr(vec::len[tup(ident, def_id)](*locals)) + + " locals"); + ret res; } @@ -91,7 +100,7 @@ fn mk_fn_info_item (&crate_ctxt ccx, &@item i) -> () { ccx.fm.insert(id, f_inf); } case (item_obj(?i,?o,?ty_params,?odid,?a)) { - auto all_methods = _vec::clone[@method](o.methods); + auto all_methods = vec::clone[@method](o.methods); plus_option[@method](all_methods, o.dtor); auto f_inf; for (@method m in all_methods) { @@ -109,7 +118,7 @@ fn mk_fn_info_item (&crate_ctxt ccx, &@item i) -> () { fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) -> () { let ast_visitor vars_visitor = walk::default_visitor(); vars_visitor = rec(visit_item_post=bind mk_fn_info_item(ccx,_) - with vars_visitor); + with vars_visitor); walk_crate(vars_visitor, *c); } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index adcfc496319b8..30437a4eeb580 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -9,13 +9,14 @@ import tstate::ann::get_post; import tstate::ann::postcond; import tstate::ann::true_precond; import tstate::ann::false_postcond; -import tstate::ann::empty_pre_post; import tstate::ann::empty_poststate; import tstate::ann::require_and_preserve; import tstate::ann::union; import tstate::ann::intersect; import tstate::ann::pp_clone; import tstate::ann::empty_prestate; +import tstate::ann::set_precondition; +import tstate::ann::set_postcondition; import aux::var_info; import aux::crate_ctxt; import aux::fn_ctxt; @@ -23,7 +24,10 @@ import aux::num_locals; import aux::expr_pp; import aux::stmt_pp; import aux::block_pp; +import aux::clear_pp; +import aux::clear_precond; import aux::set_pre_and_post; +import aux::copy_pre_post; import aux::expr_precond; import aux::expr_postcond; import aux::expr_prestate; @@ -33,6 +37,8 @@ import aux::fn_info; import aux::log_pp; import aux::ann_to_def; import aux::ann_to_def_strict; +import aux::ann_to_ts_ann; +import aux::set_postcond_false; import bitvectors::seq_preconds; import bitvectors::union_postconds; @@ -145,6 +151,8 @@ import util::common::field_exprs; import util::common::has_nonlocal_exits; import util::common::log_stmt; import util::common::log_expr_err; +import util::common::log_block_err; +import util::common::log_block; fn find_pre_post_mod(&_mod m) -> _mod { log("implement find_pre_post_mod!"); @@ -209,6 +217,11 @@ fn find_pre_post_item(&crate_ctxt ccx, &item i) -> () { the preconditions for , and the postcondition in a to be the union of all postconditions for */ fn find_pre_post_exprs(&fn_ctxt fcx, &vec[@expr] args, ann a) { + if (vec::len[@expr](args) > 0u) { + log ("find_pre_post_exprs: oper ="); + log_expr(*(args.(0))); + } + auto enclosing = fcx.enclosing; auto fm = fcx.ccx.fm; auto nv = num_locals(enclosing); @@ -220,37 +233,40 @@ fn find_pre_post_exprs(&fn_ctxt fcx, &vec[@expr] args, ann a) { vec::map[@expr, ()](f, args); - fn get_pp(&@expr e) -> pre_and_post { - ret expr_pp(e); + fn get_pp(crate_ctxt ccx, &@expr e) -> pre_and_post { + ret expr_pp(ccx, e); } - auto g = get_pp; + + auto g = bind get_pp(fcx.ccx, _); auto pps = vec::map[@expr, pre_and_post](g, args); auto h = get_post; - set_pre_and_post(a, - rec(precondition=seq_preconds(enclosing, pps), - postcondition=union_postconds - (nv, (vec::map[pre_and_post, postcond](h, pps))))); + set_pre_and_post(fcx.ccx, a, seq_preconds(enclosing, pps), + union_postconds + (nv, (vec::map[pre_and_post, postcond](h, pps)))); } fn find_pre_post_loop(&fn_ctxt fcx, &@decl d, &@expr index, &block body, &ann a) -> () { find_pre_post_expr(fcx, 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(index), - block_pp(body)])); + seq_preconds(fcx.enclosing, [expr_pp(fcx.ccx, index), + block_pp(fcx.ccx, body)])); auto loop_postcond = intersect_postconds - ([expr_postcond(index), block_postcond(body)]); - set_pre_and_post(a, rec(precondition=loop_precond, - postcondition=loop_postcond)); + ([expr_postcond(fcx.ccx, index), block_postcond(fcx.ccx, body)]); + set_pre_and_post(fcx.ccx, a, loop_precond, loop_postcond); } -fn gen_if_local(&fn_ctxt fcx, @expr lhs, @expr rhs, &ann larger_ann, &ann new_var) -> () { +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); - set_pre_and_post(larger_ann, expr_pp(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); } @@ -265,15 +281,10 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { fn do_rand_(fn_ctxt fcx, &@expr e) -> () { find_pre_post_expr(fcx, e); } - fn pp_one(&@expr e) -> pre_and_post { - ret expr_pp(e); - } - /* - log_err("find_pre_post_expr (num_locals =" + + log("find_pre_post_expr (num_locals =" + uistr(num_local_vars) + "):"); - log_expr_err(*e); - */ + log_expr(*e); alt (e.node) { case (expr_call(?operator, ?operands, ?a)) { @@ -293,9 +304,10 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { find_pre_post_exprs(fcx, elt_exprs(elts), a); } case (expr_path(?p, ?a)) { - auto res = empty_pre_post(num_local_vars); - - auto df = ann_to_def_strict(fcx.ccx, a); + auto res = expr_pp(fcx.ccx, e); + clear_pp(res); + + auto df = ann_to_def_strict(fcx.ccx, a); alt (df) { case (def_local(?d_id)) { auto i = bit_num(d_id, enclosing); @@ -303,37 +315,33 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { } case (_) { /* nothing to check */ } } - - // Otherwise, variable is global, so it must be initialized - set_pre_and_post(a, res); } case (expr_self_method(?v, ?a)) { - /* v is a method of the enclosing obj, so it must be - initialized, right? */ - set_pre_and_post(a, empty_pre_post(num_local_vars)); + clear_pp(expr_pp(fcx.ccx, e)); } case(expr_log(_, ?arg, ?a)) { find_pre_post_expr(fcx, arg); - set_pre_and_post(a, expr_pp(arg)); + copy_pre_post(fcx.ccx, a, arg); } case (expr_chan(?arg, ?a)) { find_pre_post_expr(fcx, arg); - set_pre_and_post(a, expr_pp(arg)); + copy_pre_post(fcx.ccx, a, arg); } case(expr_put(?opt, ?a)) { alt (opt) { case (some[@expr](?arg)) { find_pre_post_expr(fcx, arg); - set_pre_and_post(a, expr_pp(arg)); + copy_pre_post(fcx.ccx, a, arg); } case (none[@expr]) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); + clear_pp(expr_pp(fcx.ccx, e)); } } } case (expr_block(?b, ?a)) { find_pre_post_block(fcx, b); - set_pre_and_post(a, block_pp(b)); + auto p = block_pp(fcx.ccx, b); + set_pre_and_post(fcx.ccx, a, p.precondition, p.postcondition); } case (expr_rec(?fields,?maybe_base,?a)) { auto es = field_exprs(fields); @@ -343,7 +351,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { case (expr_assign(?lhs, ?rhs, ?a)) { alt (lhs.node) { case (expr_path(?p, ?a_lhs)) { - gen_if_local(fcx, lhs, rhs, a, a_lhs); + gen_if_local(fcx, lhs, rhs, a, a_lhs); } case (_) { find_pre_post_exprs(fcx, [lhs, rhs], a); @@ -353,7 +361,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { case (expr_recv(?lhs, ?rhs, ?a)) { alt (lhs.node) { case (expr_path(?p, ?a_lhs)) { - gen_if_local(fcx, lhs, rhs, a, a_lhs); + gen_if_local(fcx, lhs, rhs, a, a_lhs); } case (_) { // doesn't check that lhs is an lval, but @@ -368,63 +376,65 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { find_pre_post_exprs(fcx, [lhs, rhs], a); } case (expr_lit(_,?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); + clear_pp(expr_pp(fcx.ccx, e)); } case (expr_ret(?maybe_val, ?a)) { alt (maybe_val) { case (none[@expr]) { - set_pre_and_post(a, - rec(precondition=true_precond(num_local_vars), - postcondition=false_postcond(num_local_vars))); + clear_precond(fcx.ccx, a); + set_postcond_false(fcx.ccx, a); } case (some[@expr](?ret_val)) { find_pre_post_expr(fcx, ret_val); - let pre_and_post pp = - rec(precondition=expr_precond(ret_val), - postcondition=false_postcond(num_local_vars)); - set_pre_and_post(a, pp); + set_precondition(ann_to_ts_ann(fcx.ccx, a), + expr_precond(fcx.ccx, ret_val)); + set_postcond_false(fcx.ccx, a); } } } case (expr_be(?e, ?a)) { find_pre_post_expr(fcx, e); - set_pre_and_post(a, - rec(precondition=expr_prestate(e), - postcondition=false_postcond(num_local_vars))); + set_pre_and_post(fcx.ccx, a, + expr_prestate(fcx.ccx, e), + false_postcond(num_local_vars)); } case (expr_if(?antec, ?conseq, ?maybe_alt, ?a)) { find_pre_post_expr(fcx, antec); find_pre_post_block(fcx, conseq); alt (maybe_alt) { case (none[@expr]) { + log "333"; auto precond_res = seq_preconds(enclosing, - [expr_pp(antec), - block_pp(conseq)]); - set_pre_and_post(a, rec(precondition=precond_res, - postcondition= - expr_poststate(antec))); + [expr_pp(fcx.ccx, antec), + block_pp(fcx.ccx, conseq)]); + set_pre_and_post(fcx.ccx, a, precond_res, + expr_poststate(fcx.ccx, antec)); } case (some[@expr](?altern)) { find_pre_post_expr(fcx, altern); + log "444"; auto precond_true_case = seq_preconds(enclosing, - [expr_pp(antec), block_pp(conseq)]); + [expr_pp(fcx.ccx, antec), + block_pp(fcx.ccx, conseq)]); auto postcond_true_case = union_postconds (num_local_vars, - [expr_postcond(antec), block_postcond(conseq)]); + [expr_postcond(fcx.ccx, antec), + block_postcond(fcx.ccx, conseq)]); + log "555"; auto precond_false_case = seq_preconds (enclosing, - [expr_pp(antec), expr_pp(altern)]); + [expr_pp(fcx.ccx, antec), expr_pp(fcx.ccx, altern)]); auto postcond_false_case = union_postconds (num_local_vars, - [expr_postcond(antec), expr_postcond(altern)]); + [expr_postcond(fcx.ccx, antec), + expr_postcond(fcx.ccx, altern)]); auto precond_res = union_postconds (num_local_vars, [precond_true_case, precond_false_case]); auto postcond_res = intersect_postconds ([postcond_true_case, postcond_false_case]); - set_pre_and_post(a, rec(precondition=precond_res, - postcondition=postcond_res)); + set_pre_and_post(fcx.ccx, a, precond_res, postcond_res); } } } @@ -438,41 +448,42 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { } case (expr_unary(_,?operand,?a)) { find_pre_post_expr(fcx, operand); - set_pre_and_post(a, expr_pp(operand)); + copy_pre_post(fcx.ccx, a, operand); } case (expr_cast(?operand, _, ?a)) { find_pre_post_expr(fcx, operand); - set_pre_and_post(a, expr_pp(operand)); + copy_pre_post(fcx.ccx, a, operand); } case (expr_while(?test, ?body, ?a)) { find_pre_post_expr(fcx, test); find_pre_post_block(fcx, body); - set_pre_and_post(a, - rec(precondition= + log "666"; + set_pre_and_post(fcx.ccx, a, seq_preconds(enclosing, - [expr_pp(test), - block_pp(body)]), - postcondition= - intersect_postconds([expr_postcond(test), - block_postcond(body)]))); + [expr_pp(fcx.ccx, test), + block_pp(fcx.ccx, body)]), + intersect_postconds([expr_postcond(fcx.ccx, test), + block_postcond(fcx.ccx, body)])); } case (expr_do_while(?body, ?test, ?a)) { find_pre_post_block(fcx, body); find_pre_post_expr(fcx, test); auto loop_postcond = union_postconds(num_local_vars, - [block_postcond(body), expr_postcond(test)]); + [block_postcond(fcx.ccx, body), + expr_postcond(fcx.ccx, test)]); /* conservative approximination: if the body could break or cont, the test may never be executed */ if (has_nonlocal_exits(body)) { loop_postcond = empty_poststate(num_local_vars); } - set_pre_and_post(a, - rec(precondition=seq_preconds(enclosing, - [block_pp(body), - expr_pp(test)]), - postcondition=loop_postcond)); + log "777"; + set_pre_and_post(fcx.ccx, a, + seq_preconds(enclosing, + [block_pp(fcx.ccx, body), + expr_pp(fcx.ccx, test)]), + loop_postcond); } case (expr_for(?d, ?index, ?body, ?a)) { find_pre_post_loop(fcx, d, index, body, a); @@ -487,47 +498,49 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { find_pre_post_expr(fcx, e); fn do_an_alt(&fn_ctxt fcx, &arm an_alt) -> pre_and_post { find_pre_post_block(fcx, an_alt.block); - ret block_pp(an_alt.block); + ret block_pp(fcx.ccx, an_alt.block); } 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, &pre_and_post next) -> pre_and_post { + log "777"; union(pp.precondition, seq_preconds(enclosing, [antec, next])); intersect(pp.postcondition, next.postcondition); ret pp; } - auto antec_pp = pp_clone(expr_pp(e)); - auto e_pp = rec(precondition=empty_prestate(num_local_vars), + 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 alts_overall_pp = vec::foldl[pre_and_post, pre_and_post] (g, e_pp, alt_pps); - set_pre_and_post(a, alts_overall_pp); + set_pre_and_post(fcx.ccx, a, alts_overall_pp.precondition, + alts_overall_pp.postcondition); } case (expr_field(?operator, _, ?a)) { find_pre_post_expr(fcx, operator); - set_pre_and_post(a, expr_pp(operator)); + copy_pre_post(fcx.ccx, a, operator); } case (expr_fail(?a)) { - set_pre_and_post(a, + set_pre_and_post(fcx.ccx, a, /* if execution continues after fail, then everything is true! */ - rec(precondition=empty_prestate(num_local_vars), - postcondition=false_postcond(num_local_vars))); + empty_prestate(num_local_vars), + false_postcond(num_local_vars)); } case (expr_assert(?p, ?a)) { find_pre_post_expr(fcx, p); - set_pre_and_post(a, expr_pp(p)); + copy_pre_post(fcx.ccx, a, p); } case (expr_check(?p, ?a)) { /* will need to change when we support arbitrary predicates... */ find_pre_post_expr(fcx, p); - set_pre_and_post(a, expr_pp(p)); + copy_pre_post(fcx.ccx, a, p); } case(expr_bind(?operator, ?maybe_args, ?a)) { auto args = vec::cat_options[@expr](maybe_args); @@ -535,17 +548,17 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () { find_pre_post_exprs(fcx, args, a); } case (expr_break(?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); + clear_pp(expr_pp(fcx.ccx, e)); } case (expr_cont(?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); + clear_pp(expr_pp(fcx.ccx, e)); } case (expr_port(?a)) { - set_pre_and_post(a, empty_pre_post(num_local_vars)); + clear_pp(expr_pp(fcx.ccx, e)); } case (expr_ext(_, _, _, ?expanded, ?a)) { find_pre_post_expr(fcx, expanded); - set_pre_and_post(a, expr_pp(expanded)); + copy_pre_post(fcx.ccx, a, expanded); } } } @@ -565,12 +578,11 @@ fn find_pre_post_stmt(&fn_ctxt fcx, &stmt s) alt(alocal.init) { case(some[initializer](?an_init)) { find_pre_post_expr(fcx, an_init.expr); - auto rhs_pp = expr_pp(an_init.expr); - set_pre_and_post(alocal.ann, rhs_pp); + copy_pre_post(fcx.ccx, alocal.ann, an_init.expr); /* Inherit ann from initializer, and add var being initialized to the postcondition */ - set_pre_and_post(a, rhs_pp); + copy_pre_post(fcx.ccx, a, an_init.expr); /* log("gen (decl):"); log_stmt(s); */ gen(fcx, a, alocal.id); @@ -580,22 +592,21 @@ fn find_pre_post_stmt(&fn_ctxt fcx, &stmt s) log_pp(stmt_pp(s)); */ } case(none[initializer]) { - auto pp = empty_pre_post(num_local_vars); - set_pre_and_post(alocal.ann, pp); - set_pre_and_post(a, pp); + clear_pp(ann_to_ts_ann(fcx.ccx, + alocal.ann).conditions); + clear_pp(ann_to_ts_ann(fcx.ccx, a).conditions); } } } case(decl_item(?anitem)) { - auto pp = empty_pre_post(num_local_vars); - set_pre_and_post(a, pp); + clear_pp(ann_to_ts_ann(fcx.ccx, a).conditions); find_pre_post_item(fcx.ccx, *anitem); } } } case(stmt_expr(?e,?a)) { find_pre_post_expr(fcx, e); - set_pre_and_post(a, expr_pp(e)); + copy_pre_post(fcx.ccx, a, e); } } } @@ -624,7 +635,7 @@ fn find_pre_post_block(&fn_ctxt fcx, block b) -> () { log("pre_post for stmt:"); log_stmt(*s); log("is:"); - log_pp(stmt_pp(*s)); + log_pp(stmt_pp(fcx.ccx, *s)); } auto do_one = bind do_one_(fcx, _); @@ -637,15 +648,15 @@ fn find_pre_post_block(&fn_ctxt fcx, block b) -> () { let vec[pre_and_post] pps = []; - fn get_pp_stmt(&@stmt s) -> pre_and_post { - ret stmt_pp(*s); + fn get_pp_stmt(crate_ctxt ccx, &@stmt s) -> pre_and_post { + ret stmt_pp(ccx, *s); } - auto f = get_pp_stmt; + auto f = bind get_pp_stmt(fcx.ccx,_); pps += vec::map[@stmt, pre_and_post](f, b.node.stmts); - fn get_pp_expr(&@expr e) -> pre_and_post { - ret expr_pp(e); + fn get_pp_expr(crate_ctxt ccx, &@expr e) -> pre_and_post { + ret expr_pp(ccx, e); } - auto g = get_pp_expr; + auto g = bind get_pp_expr(fcx.ccx, _); plus_option[pre_and_post](pps, option::map[@expr, pre_and_post](g, b.node.expr)); @@ -661,8 +672,7 @@ fn find_pre_post_block(&fn_ctxt fcx, block b) -> () { block_postcond = union_postconds(nv, postconds); } - set_pre_and_post(b.node.a, rec(precondition=block_precond, - postcondition=block_postcond)); + set_pre_and_post(fcx.ccx, b.node.a, block_precond, block_postcond); } fn find_pre_post_fn(&fn_ctxt fcx, &_fn f) -> () { diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index 9352541ae7847..9c0ca53410e99 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -17,7 +17,6 @@ import tstate::ann::empty_poststate; import tstate::ann::require_and_preserve; import tstate::ann::union; import tstate::ann::intersect; -import tstate::ann::pp_clone; import tstate::ann::empty_prestate; import tstate::ann::prestate; import tstate::ann::poststate; @@ -181,7 +180,7 @@ fn seq_states(&fn_ctxt fcx, prestate pres, vec[@expr] exprs) for (@expr e in exprs) { changed = find_pre_post_state_expr(fcx, post, e) || changed; - post = expr_poststate(e); + post = expr_poststate(fcx.ccx, e); } ret tup(changed, post); @@ -191,8 +190,8 @@ fn find_pre_post_state_exprs(&fn_ctxt fcx, &prestate pres, &ann a, &vec[@expr] es) -> bool { auto res = seq_states(fcx, pres, es); auto changed = res._0; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, res._1) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, res._1) || changed; ret changed; } @@ -201,16 +200,16 @@ fn find_pre_post_state_loop(&fn_ctxt fcx, prestate pres, &@decl d, auto changed = false; /* same issues as while */ - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, index) || changed; /* in general, would need the intersection of (poststate of index, poststate of body) */ - changed = find_pre_post_state_block(fcx, expr_poststate(index), body) - || changed; - auto res_p = intersect_postconds([expr_poststate(index), - block_poststate(body)]); + changed = find_pre_post_state_block(fcx, + expr_poststate(fcx.ccx, index), body) || changed; + auto res_p = intersect_postconds([expr_poststate(fcx.ccx, index), + block_poststate(fcx.ccx, body)]); - changed = extend_poststate_ann(a, res_p) || changed; + changed = extend_poststate_ann(fcx.ccx, a, res_p) || changed; ret changed; } @@ -245,83 +244,85 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { || changed; /* rands go left-to-right */ changed = find_pre_post_state_exprs(fcx, - expr_poststate(operator), a, operands) - || changed; + expr_poststate(fcx.ccx, operator), a, operands) || changed; /* if this is a failing call, it sets the return value */ alt (controlflow_expr(fcx.ccx, operator)) { case (noreturn) { - /* - log_err("Call that might fail! to"); - log_expr_err(*operator); - */ - changed = gen_poststate(fcx, a, fcx.id) || changed; + /* + log_err("Call that might fail! to"); + log_expr_err(*operator); + */ + changed = gen_poststate(fcx, a, fcx.id) || changed; } case (_) { - /* log_err("non-failing call, to:"); - log_expr_err(*operator); - */ - } + /* log_err("non-failing call, to:"); + log_expr_err(*operator); + */ + } } ret changed; } case (expr_spawn(_, _, ?operator, ?operands, ?a)) { changed = find_pre_post_state_expr(fcx, pres, operator); ret(find_pre_post_state_exprs(fcx, - expr_poststate(operator), a, operands) + expr_poststate(fcx.ccx, operator), a, operands) || changed); } case (expr_bind(?operator, ?maybe_args, ?a)) { changed = find_pre_post_state_expr(fcx, pres, operator) || changed; ret (find_pre_post_state_exprs(fcx, - expr_poststate(operator), a, cat_options[@expr](maybe_args)) - || changed); + expr_poststate(fcx.ccx, operator), a, + cat_options[@expr](maybe_args)) || changed); } case (expr_path(_,?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } case (expr_log(_,?e,?a)) { /* factor out the "one exp" pattern */ changed = find_pre_post_state_expr(fcx, pres, e); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(e)) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, e)) || changed; ret changed; } case (expr_chan(?e, ?a)) { changed = find_pre_post_state_expr(fcx, pres, e); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(e)) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, e)) || changed; ret changed; } case (expr_ext(_, _, _, ?expanded, ?a)) { changed = find_pre_post_state_expr(fcx, pres, expanded); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(expanded)) - || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, expanded)) || changed; ret changed; } case (expr_put(?maybe_e, ?a)) { alt (maybe_e) { case (some[@expr](?arg)) { changed = find_pre_post_state_expr(fcx, pres, arg); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(arg)) - || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, arg)) || changed; ret changed; } case (none[@expr]) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } } } case (expr_lit(?l,?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } case (expr_block(?b,?a)) { changed = find_pre_post_state_block(fcx, pres, b) || changed; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, block_poststate(b)) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + block_poststate(fcx.ccx, b)) || changed; ret changed; } case (expr_rec(?fields,?maybe_base,?a)) { @@ -332,23 +333,23 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { case (some[@expr](?base)) { changed = find_pre_post_state_expr(fcx, pres, base) || changed; - changed = extend_poststate_ann(a, expr_poststate(base)) - || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, base)) || changed; } } ret changed; } case (expr_assign(?lhs, ?rhs, ?a)) { - extend_prestate_ann(a, pres); + extend_prestate_ann(fcx.ccx, a, pres); alt (lhs.node) { case (expr_path(?p, ?a_lhs)) { // assignment to local var - changed = pure_exp(a_lhs, pres) || changed; + changed = pure_exp(fcx.ccx, a_lhs, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, rhs) || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) - || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; changed = gen_if_local(fcx, a_lhs, a)|| changed; } case (_) { @@ -356,24 +357,24 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { changed = find_pre_post_state_expr(fcx, pres, lhs) || changed; changed = find_pre_post_state_expr(fcx, - expr_poststate(lhs), rhs) || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) - || changed; + expr_poststate(fcx.ccx, lhs), rhs) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; } } ret changed; } case (expr_recv(?lhs, ?rhs, ?a)) { - extend_prestate_ann(a, pres); + extend_prestate_ann(fcx.ccx, a, pres); alt (lhs.node) { case (expr_path(?p, ?a_lhs)) { // receive to local var - changed = pure_exp(a_lhs, pres) || changed; + changed = pure_exp(fcx.ccx, a_lhs, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, rhs) || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) - || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; changed = gen_if_local(fcx, a_lhs, a) || changed; } case (_) { @@ -381,17 +382,17 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { changed = find_pre_post_state_expr(fcx, pres, lhs) || changed; changed = find_pre_post_state_expr(fcx, - expr_poststate(lhs), rhs) || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) - || changed; + expr_poststate(fcx.ccx, lhs), rhs) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; } } ret changed; } case (expr_ret(?maybe_ret_val, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - set_poststate_ann(a, false_postcond(num_local_vars)); + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + set_poststate_ann(fcx.ccx, a, false_postcond(num_local_vars)); alt(maybe_ret_val) { case (none[@expr]) { /* do nothing */ } case (some[@expr](?ret_val)) { @@ -402,28 +403,30 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { ret changed; } case (expr_be(?e, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; - set_poststate_ann(a, false_postcond(num_local_vars)); + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + set_poststate_ann(fcx.ccx, a, false_postcond(num_local_vars)); changed = find_pre_post_state_expr(fcx, pres, e) || changed; ret changed; } case (expr_if(?antec, ?conseq, ?maybe_alt, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, antec) || changed; changed = find_pre_post_state_block(fcx, - expr_poststate(antec), conseq) || changed; + expr_poststate(fcx.ccx, antec), conseq) || changed; alt (maybe_alt) { case (none[@expr]) { - changed = extend_poststate_ann(a, expr_poststate(antec)) - || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, antec)) || changed; } case (some[@expr](?altern)) { changed = find_pre_post_state_expr(fcx, - expr_poststate(antec), altern) || changed; + expr_poststate(fcx.ccx, antec), altern) || changed; auto poststate_res = intersect_postconds - ([block_poststate(conseq), expr_poststate(altern)]); - changed = extend_poststate_ann(a, poststate_res) || changed; + ([block_poststate(fcx.ccx, conseq), + expr_poststate(fcx.ccx, altern)]); + changed = extend_poststate_ann(fcx.ccx, a, poststate_res) + || changed; } } log("if:"); @@ -431,41 +434,44 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { log("new prestate:"); log_bitv(fcx.enclosing, pres); log("new poststate:"); - log_bitv(fcx.enclosing, expr_poststate(e)); + log_bitv(fcx.enclosing, expr_poststate(fcx.ccx, e)); ret changed; } case (expr_binary(?bop, ?l, ?r, ?a)) { /* FIXME: what if bop is lazy? */ - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, l) || changed; - changed = find_pre_post_state_expr(fcx, expr_poststate(l), r) + changed = find_pre_post_state_expr(fcx, expr_poststate(fcx.ccx, l), r) || changed; - changed = extend_poststate_ann(a, expr_poststate(r)) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, r)) || changed; ret changed; } case (expr_send(?l, ?r, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, l) || changed; - changed = find_pre_post_state_expr(fcx, expr_poststate(l), r) + changed = find_pre_post_state_expr(fcx, expr_poststate(fcx.ccx, l), r) || changed; - changed = extend_poststate_ann(a, expr_poststate(r)) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, r)) || changed; ret changed; } case (expr_assign_op(?op, ?lhs, ?rhs, ?a)) { /* quite similar to binary -- should abstract this */ - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, lhs) || changed; - changed = find_pre_post_state_expr(fcx, expr_poststate(lhs), rhs) - || changed; - changed = extend_poststate_ann(a, expr_poststate(rhs)) || changed; + changed = find_pre_post_state_expr(fcx, + expr_poststate(fcx.ccx, lhs), rhs) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, rhs)) || changed; ret changed; } case (expr_while(?test, ?body, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; /* to handle general predicates, we need to pass in pres `intersect` (poststate(a)) like: auto test_pres = intersect_postconds(pres, expr_postcond(a)); @@ -476,30 +482,30 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { */ changed = find_pre_post_state_expr(fcx, pres, test) || changed; - changed = find_pre_post_state_block(fcx, expr_poststate(test), body) - || changed; - changed = extend_poststate_ann(a, - intersect_postconds([expr_poststate(test), - block_poststate(body)])) || changed; + changed = find_pre_post_state_block(fcx, + expr_poststate(fcx.ccx, test), body) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + intersect_postconds([expr_poststate(fcx.ccx, test), + block_poststate(fcx.ccx, body)])) || changed; ret changed; } case (expr_do_while(?body, ?test, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_block(fcx, pres, body) || changed; changed = find_pre_post_state_expr(fcx, - block_poststate(body), test) || changed; + block_poststate(fcx.ccx, body), test) || changed; /* conservative approximination: if the body of the loop could break or cont, we revert to the prestate (TODO: could treat cont differently from break, since if there's a cont, the test will execute) */ if (has_nonlocal_exits(body)) { - changed = set_poststate_ann(a, pres) || changed; + changed = set_poststate_ann(fcx.ccx, a, pres) || changed; } else { - changed = extend_poststate_ann(a, expr_poststate(test)) - || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, test)) || changed; } ret changed; @@ -511,155 +517,160 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool { ret find_pre_post_state_loop(fcx, pres, d, index, body, a); } case (expr_index(?e, ?sub, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, e) || changed; changed = find_pre_post_state_expr(fcx, - expr_poststate(e), sub) || changed; - changed = extend_poststate_ann(a, expr_poststate(sub)); + expr_poststate(fcx.ccx, e), sub) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, sub)); ret changed; } case (expr_alt(?e, ?alts, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, e) || changed; - auto e_post = expr_poststate(e); + auto e_post = expr_poststate(fcx.ccx, e); auto a_post; if (vec::len[arm](alts) > 0u) { a_post = false_postcond(num_local_vars); for (arm an_alt in alts) { changed = find_pre_post_state_block(fcx, e_post, an_alt.block) || changed; - changed = intersect(a_post, block_poststate(an_alt.block)) - || changed; + changed = intersect(a_post, + block_poststate(fcx.ccx, + an_alt.block)) || changed; } } else { // No alts; poststate is the poststate of the test a_post = e_post; } - changed = extend_poststate_ann(a, a_post); + changed = extend_poststate_ann(fcx.ccx, a, a_post); ret changed; } case (expr_field(?e, _, ?a)) { changed = find_pre_post_state_expr(fcx, pres, e); - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(e)) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, e)) || changed; ret changed; } case (expr_unary(_,?operand,?a)) { changed = find_pre_post_state_expr(fcx, pres, operand) || changed; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(operand)) - || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, operand)) || changed; ret changed; } case (expr_cast(?operand, _, ?a)) { changed = find_pre_post_state_expr(fcx, pres, operand) || changed; - changed = extend_prestate_ann(a, pres) || changed; - changed = extend_poststate_ann(a, expr_poststate(operand)) - || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, + expr_poststate(fcx.ccx, operand)) || changed; ret changed; } case (expr_fail(?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; /* if execution continues after fail, then everything is true! woo! */ - changed = set_poststate_ann(a, false_postcond(num_local_vars)) - || changed; + changed = set_poststate_ann(fcx.ccx, a, + false_postcond(num_local_vars)) || changed; ret changed; } case (expr_assert(?p, ?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } case (expr_check(?p, ?a)) { - changed = extend_prestate_ann(a, pres) || changed; + changed = extend_prestate_ann(fcx.ccx, a, pres) || changed; changed = find_pre_post_state_expr(fcx, pres, p) || changed; /* FIXME: update the postcondition to reflect that p holds */ - changed = extend_poststate_ann(a, pres) || changed; + changed = extend_poststate_ann(fcx.ccx, a, pres) || changed; ret changed; } case (expr_break(?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } case (expr_cont(?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } case (expr_port(?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } case (expr_self_method(_, ?a)) { - ret pure_exp(a, pres); + ret pure_exp(fcx.ccx, a, pres); } } } fn find_pre_post_state_stmt(&fn_ctxt fcx, &prestate pres, @stmt s) -> bool { - auto changed = false; - auto stmt_ann_ = stmt_to_ann(*s); - assert (!is_none[@ts_ann](stmt_ann_)); - auto stmt_ann = *(get[@ts_ann](stmt_ann_)); - log("*At beginning: stmt = "); - log_stmt(*s); - log("*prestate = "); - log(bitv::to_str(stmt_ann.states.prestate)); - log("*poststate ="); - log(bitv::to_str(stmt_ann.states.poststate)); - log("*changed ="); - log(changed); + auto changed = false; + auto stmt_ann = stmt_to_ann(fcx.ccx, *s); + + log("*At beginning: stmt = "); + log_stmt(*s); + log("*prestate = "); + log(bitv::to_str(stmt_ann.states.prestate)); + log("*poststate ="); + log(bitv::to_str(stmt_ann.states.poststate)); + log("*changed ="); + log(changed); - alt (s.node) { - case (stmt_decl(?adecl, ?a)) { - alt (adecl.node) { - case (decl_local(?alocal)) { - alt (alocal.init) { - case (some[initializer](?an_init)) { - changed = extend_prestate(stmt_ann.states.prestate, pres) - || changed; - changed = find_pre_post_state_expr - (fcx, pres, an_init.expr) || changed; - changed = extend_poststate(stmt_ann.states.poststate, - expr_poststate(an_init.expr)) - || changed; - changed = gen_poststate(fcx, a, alocal.id) - || changed; - log("Summary: stmt = "); - log_stmt(*s); - log("prestate = "); - log(bitv::to_str(stmt_ann.states.prestate)); - log_bitv(fcx.enclosing, stmt_ann.states.prestate); - log("poststate ="); - log_bitv(fcx.enclosing, stmt_ann.states.poststate); - log("changed ="); - log(changed); + alt (s.node) { + case (stmt_decl(?adecl, ?a)) { + alt (adecl.node) { + case (decl_local(?alocal)) { + alt (alocal.init) { + case (some[initializer](?an_init)) { + changed = extend_prestate + (stmt_ann.states.prestate, pres) || changed; + changed = find_pre_post_state_expr + (fcx, pres, an_init.expr) || changed; + changed = extend_poststate + (stmt_ann.states.poststate, + expr_poststate(fcx.ccx, an_init.expr)) + || changed; + changed = gen_poststate(fcx, a, alocal.id) + || changed; + log("Summary: stmt = "); + log_stmt(*s); + log("prestate = "); + log(bitv::to_str(stmt_ann.states.prestate)); + log_bitv(fcx.enclosing, stmt_ann.states.prestate); + log("poststate ="); + log_bitv(fcx.enclosing, + stmt_ann.states.poststate); + log("changed ="); + log(changed); - ret changed; - } - case (none[initializer]) { - changed = extend_prestate(stmt_ann.states.prestate, pres) - || changed; - changed = extend_poststate(stmt_ann.states.poststate, pres) - || changed; - ret changed; + ret changed; + } + case (none[initializer]) { + changed = extend_prestate + (stmt_ann.states.prestate, pres) || changed; + changed = extend_poststate + (stmt_ann.states.poststate, pres) || changed; + ret changed; + } + } + } + case (decl_item(?an_item)) { + changed = extend_prestate(stmt_ann.states.prestate, pres) + || changed; + changed = extend_poststate(stmt_ann.states.poststate, + pres) || changed; + ret (find_pre_post_state_item(fcx, an_item) || changed); + } } - } } - case (decl_item(?an_item)) { - changed = extend_prestate(stmt_ann.states.prestate, pres) - || changed; - changed = extend_poststate(stmt_ann.states.poststate, pres) - || changed; - ret (find_pre_post_state_item(fcx, an_item) || changed); - } - } - } - case (stmt_expr(?e, _)) { - changed = find_pre_post_state_expr(fcx, pres, e) || changed; - changed = extend_prestate(stmt_ann.states.prestate, expr_prestate(e)) - || changed; - changed = extend_poststate(stmt_ann.states.poststate, - expr_poststate(e)) || changed; - /* - log("Summary: stmt = "); + case (stmt_expr(?e, _)) { + changed = find_pre_post_state_expr(fcx, pres, e) || changed; + changed = extend_prestate(stmt_ann.states.prestate, + expr_prestate(fcx.ccx, e)) + || changed; + changed = extend_poststate(stmt_ann.states.poststate, + expr_poststate(fcx.ccx, e)) || changed; + /* + log("Summary: stmt = "); log_stmt(*s); log("prestate = "); log(bitv::to_str(stmt_ann.states.prestate)); @@ -669,11 +680,11 @@ fn find_pre_post_state_stmt(&fn_ctxt fcx, &prestate pres, @stmt s) -> bool { log_bitv(enclosing, stmt_ann.states.poststate); log("changed ="); log(changed); - */ - ret changed; + */ + ret changed; + } + case (_) { ret false; } } - case (_) { ret false; } - } } /* Updates the pre- and post-states of statements in the block, @@ -692,7 +703,7 @@ fn find_pre_post_state_block(&fn_ctxt fcx, &prestate pres0, &block b) Then becomes the new poststate. */ for (@stmt s in b.node.stmts) { changed = find_pre_post_state_stmt(fcx, pres, s) || changed; - pres = stmt_poststate(*s, num_local_vars); + pres = stmt_poststate(fcx.ccx, *s); } auto post = pres; @@ -701,7 +712,7 @@ fn find_pre_post_state_block(&fn_ctxt fcx, &prestate pres0, &block b) case (none[@expr]) {} case (some[@expr](?e)) { changed = find_pre_post_state_expr(fcx, pres, e) || changed; - post = expr_poststate(e); + post = expr_poststate(fcx.ccx, e); } } @@ -718,13 +729,13 @@ fn find_pre_post_state_block(&fn_ctxt fcx, &prestate pres0, &block b) post = pres0; } - set_prestate_ann(b.node.a, pres0); - set_poststate_ann(b.node.a, post); + set_prestate_ann(fcx.ccx, b.node.a, pres0); + set_poststate_ann(fcx.ccx, b.node.a, post); log("For block:"); log_block(b); log("poststate = "); - log_states(block_states(b)); + log_states(block_states(fcx.ccx, b)); log("pres0:"); log_bitv(fcx.enclosing, pres0); log("post:"); @@ -785,3 +796,14 @@ fn find_pre_post_state_item(&fn_ctxt fcx, @item i) -> bool { } } } +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// + diff --git a/src/lib/bitv.rs b/src/lib/bitv.rs index 5ea8e456684c7..b2f07fa2d3876 100644 --- a/src/lib/bitv.rs +++ b/src/lib/bitv.rs @@ -114,7 +114,7 @@ fn clear(&t v) { } fn set_all(&t v) { - for each (uint i in _uint::range(0u, v.nbits)) { + for each (uint i in uint::range(0u, v.nbits)) { set(v, i, true); } } From 96048aec1a87cc3550d592b741997b9b9628a5ce Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 18 May 2011 16:15:38 -0700 Subject: [PATCH 10/10] remove now-unused ts field from ann --- src/comp/front/ast.rs | 3 +-- src/comp/front/parser.rs | 5 ++--- src/comp/middle/ty.rs | 2 +- src/comp/util/common.rs | 15 ++------------- 4 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 6bde1e42feeec..75321f595f444 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -23,8 +23,7 @@ type ty_param = ident; // Annotations added during successive passes. type ann = rec(uint id, middle::ty::t ty, - option::t[vec[middle::ty::t]] tps, - option::t[@ts_ann] ts); + option::t[vec[middle::ty::t]] tps); tag def { def_fn(def_id); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index df08e4c8d740f..3099ddfb0aee2 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -147,11 +147,10 @@ fn new_parser(session::session sess, fn get_chpos() -> uint {ret rdr.get_chpos();} fn get_ann() -> ast::ann { - // TODO: Remove ty, tps, and ts. ty and tps should be unused + // TODO: Remove ty and tps, which should be unused // by now. auto rv = rec(id=next_ann_var, ty=0u, - tps=none[vec[middle::ty::t]], - ts=none[@middle::tstate::ann::ts_ann]); + tps=none[vec[middle::ty::t]]); next_ann_var += 1u; ret rv; } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 6b2ee1441bbab..af39ccc7c4371 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1498,7 +1498,7 @@ fn ann_to_monotype(ctxt cx, &node_type_table ntt, ast::ann a) -> t { // Turns a type and optional type parameters into an annotation, using // defaults for other fields. fn mk_ann_type(uint node_id, t typ, option::t[vec[t]] tps) -> ast::ann { - ret rec(id=node_id, ty=typ, tps=tps, ts=none[@ts_ann]); + ret rec(id=node_id, ty=typ, tps=tps); } // Turns a type into an annotation, using defaults for other fields. diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index 8d62e27f5bc63..090ad57027ec5 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -178,8 +178,8 @@ fn item_to_str(&@ast::item i) -> str { auto out_ = mkstate(s.get_writer(), 80u); auto out = @rec(s=out_, comments=none[vec[front::lexer::cmnt]], - mutable cur_cmnt=0u); - + mutable cur_cmnt=0u, + mode=mo_untyped); print_item(out, i); ret s.get_str(); } @@ -196,17 +196,6 @@ fn log_item_err(&@ast::item i) -> () { log_err(item_to_str(i)); } -fn log_ann(&ast::ann a) -> () { - alt (a) { - case (ast::ann_none(_)) { - log("ann_none"); - } - case (ast::ann_type(_,_,_,_)) { - log("ann_type"); - } - } -} - fn fun_to_str(&ast::_fn f, str name, vec[ast::ty_param] params) -> str { let str_writer s = string_writer(); auto out_ = mkstate(s.get_writer(), 80u);