about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-01-02 10:20:58 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-01-02 10:20:58 +0100
commitbd6646e698c38564b8b324ec8cf30305db6a409a (patch)
tree6fb4068a45ed012ae42f8dc75d8d95e7115136f5
parent1c125d8829f38eadd62f4feef9b4f6b55b6aed7d (diff)
downloadrust-bd6646e698c38564b8b324ec8cf30305db6a409a.tar.gz
rust-bd6646e698c38564b8b324ec8cf30305db6a409a.zip
Make last-use pass properly handle closed-over variables
Closes #1399
-rw-r--r--src/comp/middle/last_use.rs21
-rw-r--r--src/test/run-pass/last-use-is-capture.rs8
2 files changed, 26 insertions, 3 deletions
diff --git a/src/comp/middle/last_use.rs b/src/comp/middle/last_use.rs
index 113e9a9c299..4d1c26ddbbc 100644
--- a/src/comp/middle/last_use.rs
+++ b/src/comp/middle/last_use.rs
@@ -63,6 +63,13 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
     ret mini_table;
 }
 
+fn is_block(cx: ctx, id: node_id) -> bool {
+    alt ty::struct(cx.tcx, ty::node_id_to_monotype(cx.tcx, id)) {
+      ty::ty_fn({proto: proto_block., _}) { true }
+      _ { false }
+    }
+}
+
 fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
     alt ex.node {
       expr_ret(oexpr) {
@@ -135,9 +142,8 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
         let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
         for arg in args {
             alt arg.node {
-              //NDM--register captured as uses
-              expr_fn(_, _, _, captured) { fns += [arg]; }
-              expr_fn_block(_, _) { fns += [arg]; }
+              expr_fn(proto_block., _, _, _) { fns += [arg]; }
+              expr_fn_block(_, _) when is_block(cx, arg.id) { fns += [arg]; }
               _ {
                 alt arg_ts[i].mode {
                   by_mut_ref. { clear_if_path(cx, arg, v, false); }
@@ -163,6 +169,15 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
             visit::visit_fn(fk, decl, body, sp, id, cx, v);
         });
     } else {
+        alt cx.tcx.freevars.find(id) {
+          some(vars) {
+            for v in *vars {
+                clear_in_current(cx, ast_util::def_id_of_def(v.def).node,
+                                 false);
+            }
+          }
+          _ {}
+        }
         let old = nil;
         cx.blocks <-> old;
         visit::visit_fn(fk, decl, body, sp, id, cx, v);
diff --git a/src/test/run-pass/last-use-is-capture.rs b/src/test/run-pass/last-use-is-capture.rs
new file mode 100644
index 00000000000..1399839a1ed
--- /dev/null
+++ b/src/test/run-pass/last-use-is-capture.rs
@@ -0,0 +1,8 @@
+// Make sure #1399 stays fixed
+
+fn main() {
+    fn invoke(f: lambda()) { f(); }
+    let k = ~22;
+    let _u = {a: k};
+    invoke {||log(error, k);}
+}