export annotate_freevars;
export freevar_map;
+export freevar_info;
export get_freevars;
export has_freevars;
// A vector of defs representing the free variables referred to in a function.
// (The def_upvar will already have been stripped).
-type freevar_info = @[ast::def];
+type freevar_entry = {
+ def: ast::def, //< The variable being accessed free.
+ span: span //< First span where it is accessed (there can be multiple)
+};
+type freevar_info = @[@freevar_entry];
type freevar_map = hashmap<ast::node_id, freevar_info>;
// Searches through part of the AST for all references to locals or
if i == depth { // Made it to end of loop
let dnum = ast_util::def_id_of_def(def).node;
if !seen.contains_key(dnum) {
- *refs += [def];
+ *refs += [@{def:def, span:expr.span}];
seen.insert(dnum, ());
}
}
fn check_free_vars(e: @expr,
cx: ctx,
check_fn: fn(ctx, ty::t, sp: span)) {
- for free in *freevars::get_freevars(cx.tcx, e.id) {
- let id = ast_util::def_id_of_def(free).node;
+ for @{def, span} in *freevars::get_freevars(cx.tcx, e.id) {
+ let id = ast_util::def_id_of_def(def).node;
let ty = ty::node_id_to_type(cx.tcx, id);
- check_fn(cx, ty, e.span);
+ check_fn(cx, ty, span);
}
}
import trans_common::*;
import trans_build::*;
import trans::*;
-import middle::freevars::get_freevars;
+import middle::freevars::{get_freevars, freevar_info};
import option::{some, none};
import back::abi;
import syntax::codemap::span;
// Given a context and a list of upvars, build a closure. This just
// collects the upvars and packages them up for store_environment.
fn build_closure(cx: @block_ctxt,
- upvars: @[ast::def],
+ upvars: freevar_info,
ck: ty::closure_kind)
-> closure_result {
// If we need to, package up the iterator body to call
let env_vals = [];
let tcx = bcx_tcx(cx);
// Package up the upvars
- vec::iter(*upvars) { |def|
- let lv = trans_local_var(cx, def);
- let nid = ast_util::def_id_of_def(def).node;
+ vec::iter(*upvars) { |upvar|
+ let lv = trans_local_var(cx, upvar.def);
+ let nid = ast_util::def_id_of_def(upvar.def).node;
let ty = ty::node_id_to_monotype(tcx, nid);
alt ck {
ty::closure_block. { ty = ty::mk_mut_ptr(tcx, ty); }
fn load_environment(enclosing_cx: @block_ctxt,
fcx: @fn_ctxt,
boxed_closure_ty: ty::t,
- upvars: @[ast::def],
+ upvars: freevar_info,
ck: ty::closure_kind) {
let bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
// Populate the upvars from the environment.
let path = [0, abi::box_rc_field_body, abi::closure_elt_bindings];
- vec::iteri(*upvars) { |i, upvar_def|
+ vec::iteri(*upvars) { |i, upvar|
check type_is_tup_like(bcx, boxed_closure_ty);
let upvarptr =
GEP_tup_like(bcx, boxed_closure_ty, llclosure, path + [i as int]);
ty::closure_block. { llupvarptr = Load(bcx, llupvarptr); }
ty::closure_send. | ty::closure_shared. { }
}
- let def_id = ast_util::def_id_of_def(upvar_def);
+ let def_id = ast_util::def_id_of_def(upvar.def);
fcx.llupvars.insert(def_id.node, llupvarptr);
}
}
expr_fn(f, _) { // NDM captures
let rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
- for def in *freevars::get_freevars(fcx.ccx.tcx, e.id) {
+ for @{def, span} in *freevars::get_freevars(fcx.ccx.tcx, e.id) {
log ("handle_var_def: def=", def);
handle_var_def(fcx, rslt, def, "upvar");
}