]> git.lizzy.rs Git - rust.git/commitdiff
when collecting free vars, track the span where it is used too
authorNiko Matsakis <niko@alum.mit.edu>
Sat, 17 Dec 2011 00:07:54 +0000 (16:07 -0800)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 19 Dec 2011 22:07:46 +0000 (14:07 -0800)
src/comp/middle/freevars.rs
src/comp/middle/kind.rs
src/comp/middle/trans_closure.rs
src/comp/middle/tstate/pre_post_conditions.rs
src/test/compile-fail/sendfn-captures-nonsendable-state.rs [new file with mode: 0644]

index 8055f49f5d873c0d4c1b95a95d05bcf37d7decd2..a7a791e52b0980834d0cedd4c10fe989f6ad07be 100644 (file)
 
 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 ignore_item(_i: @ast::item, &&_depth: int, _v: 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, ());
                     }
                 }
index 36dc4d9f65acbde4a5bce56cd7517fcd3410e5d3..d07e862ceb96e048a6adc8068c6275380f6d188b 100644 (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);
         }
     }
 
index 43cb0c3f39d45ae00fb7afeb647ecd461ea12f57..cc72ef5b3e36a583a863be0d4a08097fec2fab7c 100644 (file)
@@ -5,7 +5,7 @@
 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 maybe_clone_tydesc(bcx: @block_ctxt,
 // 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);
     }
 }
index 33ab3da4f39e02adb36098c05f6a8012b460a398..3ff12bcafc9143d7786cef7084338224822e8ecb 100644 (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");
         }
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 (file)
index 0000000..840942b
--- /dev/null
@@ -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