Fix bad interaction between last-use finding and references

The last-use pass now takes input from the alias pass to not mark things
as last uses that are still accessed through a reference.

Issue #925
This commit is contained in:
Marijn Haverbeke 2011-11-21 09:25:42 +01:00
parent ff04cb1eb0
commit 86c1f16a10
4 changed files with 32 additions and 15 deletions

View file

@ -139,8 +139,6 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
bind freevars::annotate_freevars(def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars);
time(time_passes, "typechecking", bind typeck::check_crate(ty_cx, crate));
let last_uses = time(time_passes, "last use finding",
bind last_use::find_last_uses(crate, def_map, ty_cx));
time(time_passes, "function usage",
bind fn_usage::check_crate_fn_usage(ty_cx, crate));
time(time_passes, "alt checking",
@ -150,9 +148,11 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
let mut_map =
time(time_passes, "mutability checking",
bind middle::mut::check_crate(ty_cx, crate));
let copy_map =
let (copy_map, ref_map) =
time(time_passes, "alias checking",
bind middle::alias::check_crate(ty_cx, crate));
let last_uses = time(time_passes, "last use finding",
bind last_use::find_last_uses(crate, def_map, ref_map, ty_cx));
time(time_passes, "kind checking",
bind kind::check_crate(ty_cx, last_uses, crate));
time(time_passes, "const checking",

View file

@ -36,6 +36,10 @@ type scope = {bs: [binding],
fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option::t<node_id>,
unsafe_tys: [unsafe_ty]) -> binding {
alt root_var {
some(r_id) { cx.ref_map.insert(id, r_id); }
_ {}
}
ret @{node_id: id, span: span, root_var: root_var,
local_id: local_id_of_node(cx, id),
unsafe_tys: unsafe_tys,
@ -45,16 +49,19 @@ fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option::t<node_id>,
tag local_info { local(uint); }
type copy_map = std::map::hashmap<node_id, ()>;
type ref_map = std::map::hashmap<node_id, node_id>;
type ctx = {tcx: ty::ctxt,
copy_map: copy_map,
ref_map: ref_map,
mutable silent: bool};
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> copy_map {
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) {
// Stores information about object fields and function
// arguments that's otherwise not easily available.
let cx = @{tcx: tcx,
copy_map: std::map::new_int_hash(),
ref_map: std::map::new_int_hash(),
mutable silent: false};
let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _),
visit_expr: bind visit_expr(cx, _, _, _),
@ -63,7 +70,7 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> copy_map {
let sc = {bs: [], ret_info: other, invalid: @mutable list::nil};
visit::visit_crate(*crate, sc, visit::mk_vt(v));
tcx.sess.abort_if_errors();
ret cx.copy_map;
ret (cx.copy_map, cx.ref_map);
}
fn visit_fn(cx: @ctx, f: ast::_fn, _tp: [ast::ty_param], sp: span,

View file

@ -32,18 +32,20 @@ type bl = @{type: block_type, mutable second: bool, mutable exits: [set]};
type ctx = {last_uses: std::map::hashmap<node_id, bool>,
def_map: resolve::def_map,
ref_map: alias::ref_map,
tcx: ty::ctxt,
// The current set of local last uses
mutable current: set,
mutable blocks: list<bl>};
fn find_last_uses(c: @crate, def_map: resolve::def_map, tcx: ty::ctxt)
-> last_uses {
fn find_last_uses(c: @crate, def_map: resolve::def_map,
ref_map: alias::ref_map, tcx: ty::ctxt) -> last_uses {
let v = visit::mk_vt(@{visit_expr: visit_expr,
visit_fn: visit_fn
with *visit::default_visitor()});
let cx = {last_uses: std::map::new_int_hash(),
def_map: def_map,
ref_map: ref_map,
tcx: tcx,
mutable current: [],
mutable blocks: nil};
@ -99,11 +101,17 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
cx.current = join_branches([cur, cx.current]);
}
expr_path(_) {
alt clear_if_path(cx, ex, v, false) {
option::some(my_def) {
cx.current += [{def: my_def, exprs: cons(ex.id, @nil)}];
let my_def = ast_util::def_id_of_def(cx.def_map.get(ex.id)).node;
alt cx.ref_map.find(my_def) {
option::some(root_id) { clear_in_current(cx, root_id, false); }
_ {
alt clear_if_path(cx, ex, v, false) {
option::some(my_def) {
cx.current += [{def: my_def, exprs: cons(ex.id, @nil)}];
}
_ {}
}
}
_ {}
}
}
expr_swap(lhs, rhs) {

View file

@ -4524,10 +4524,12 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
fn init_ref_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
let init_expr = option::get(local.node.init).expr;
let val = trans_lval(bcx, init_expr);
assert val.kind == owned;
ret trans_alt::bind_irrefutable_pat(val.bcx, local.node.pat, val.val,
false);
let {bcx, val, kind} = trans_lval(bcx, init_expr);
alt kind {
owned_imm. { val = do_spill_noroot(bcx, val); }
owned. {}
}
ret trans_alt::bind_irrefutable_pat(bcx, local.node.pat, val, false);
}
fn zero_alloca(cx: @block_ctxt, llptr: ValueRef, t: ty::t)