when collecting free vars, track the span where it is used too

This commit is contained in:
Niko Matsakis 2011-12-16 16:07:54 -08:00
parent 98cbbbb642
commit b0f1a5f051
5 changed files with 25 additions and 14 deletions

View file

@ -10,12 +10,17 @@ import syntax::codemap::span;
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
@ -50,7 +55,7 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn@(visit::vt<int>)) ->
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, ());
}
}

View file

@ -55,10 +55,10 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
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);
}
}

View file

@ -5,7 +5,7 @@ import llvm::{ValueRef, TypeRef};
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;
@ -261,16 +261,16 @@ fn store_environment(
// 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); }
@ -287,7 +287,7 @@ fn build_closure(cx: @block_ctxt,
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);
@ -311,7 +311,7 @@ fn load_environment(enclosing_cx: @block_ctxt,
// 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]);
@ -321,7 +321,7 @@ fn load_environment(enclosing_cx: @block_ctxt,
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);
}
}

View file

@ -342,7 +342,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
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");
}

View file

@ -0,0 +1,6 @@
// error-pattern: not a sendable value
fn main() {
let x = @3u;
let _f = sendfn(y: uint) -> uint { ret *x+y; };
}