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:
parent
ff04cb1eb0
commit
86c1f16a10
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue