diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index 8055f49f5d8..a7a791e52b0 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -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; // 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)) -> 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, ()); } } diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs index 36dc4d9f65a..d07e862ceb9 100644 --- a/src/comp/middle/kind.rs +++ b/src/comp/middle/kind.rs @@ -55,10 +55,10 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { 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); } } diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index 43cb0c3f39d..cc72ef5b3e3 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -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); } } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 33ab3da4f39..3ff12bcafc9 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -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"); } diff --git a/src/test/compile-fail/sendfn-captures-nonsendable-state.rs b/src/test/compile-fail/sendfn-captures-nonsendable-state.rs new file mode 100644 index 00000000000..840942bf723 --- /dev/null +++ b/src/test/compile-fail/sendfn-captures-nonsendable-state.rs @@ -0,0 +1,6 @@ +// error-pattern: not a sendable value + +fn main() { + let x = @3u; + let _f = sendfn(y: uint) -> uint { ret *x+y; }; +} \ No newline at end of file