about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-12-20 21:56:21 -0800
committerNiko Matsakis <niko@alum.mit.edu>2011-12-21 06:14:36 -0800
commit627217fa55ec36d94016eddd4f4fa0dacc81634d (patch)
tree9f846413bb704c61bf201110783d41cf8be61efb
parentc03d14a33ddee8001f59224b40ce2fe06a71e074 (diff)
downloadrust-627217fa55ec36d94016eddd4f4fa0dacc81634d.tar.gz
rust-627217fa55ec36d94016eddd4f4fa0dacc81634d.zip
valid cap clause for kind-ness too
-rw-r--r--src/comp/middle/kind.rs36
-rw-r--r--src/test/compile-fail/cap-clause-illegal-cap.rs10
2 files changed, 34 insertions, 12 deletions
diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs
index 88a763fb638..5784a328d42 100644
--- a/src/comp/middle/kind.rs
+++ b/src/comp/middle/kind.rs
@@ -90,18 +90,30 @@ fn check_fn_body(decl: fn_decl, body: blk, sp: span, i: fn_ident, id: node_id,
     visit::visit_fn_body(decl, body, sp, i, id, cx, v);
 }
 
-fn check_fn_cap_clause(_cx: ctx,
-                       _id: node_id,
-                       _cap_clause: capture_clause) {
-//    let freevars = freevars::get_freevars(cx.tcx, i);
-//    let contains_var = lambda(id: def_id) -> bool {
-//        vec::any(freevars, { |freevar|
-//            ast_util::def_id_of_def(freevar).node == def_id
-//        })
-//    }
-//    with_closure_check_fn(cx, id) { |check_fn|
-//        let check_var = lambda(
-//    }
+fn check_fn_cap_clause(cx: ctx,
+                       id: node_id,
+                       cap_clause: capture_clause) {
+    // Check that the variables named in the clause which are not free vars
+    // (if any) are also legal.  freevars are checked above in check_fn_body.
+    // This is kind of a degenerate case, as captured variables will generally
+    // appear free in the body.
+    let freevars = freevars::get_freevars(cx.tcx, id);
+    let freevar_ids = vec::map(*freevars, { |freevar|
+        ast_util::def_id_of_def(freevar.def).node
+    });
+    //log("freevar_ids", freevar_ids);
+    with_closure_check_fn(cx, id) { |check_fn|
+        let check_var = lambda(&&cap_item: @capture_item) {
+            let cap_def = cx.tcx.def_map.get(cap_item.id);
+            let cap_def_id = ast_util::def_id_of_def(cap_def).node;
+            if !vec::member(cap_def_id, freevar_ids) {
+                let ty = ty::node_id_to_type(cx.tcx, cap_def_id);
+                check_fn(cx, ty, cap_item.span);
+            }
+        };
+        vec::iter(cap_clause.copies, check_var);
+        vec::iter(cap_clause.moves, check_var);
+    }
 }
 
 fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
diff --git a/src/test/compile-fail/cap-clause-illegal-cap.rs b/src/test/compile-fail/cap-clause-illegal-cap.rs
new file mode 100644
index 00000000000..e2f60dbb6ab
--- /dev/null
+++ b/src/test/compile-fail/cap-clause-illegal-cap.rs
@@ -0,0 +1,10 @@
+// error-pattern: copying a noncopyable value
+
+fn to_lambda2(b: block(uint) -> uint) -> lambda(uint) -> uint {
+    // test case where copy clause specifies a value that is not used
+    // in lambda body, but value is illegal to copy:
+    ret lambda[copy b](u: uint) -> uint { 22u };
+}
+
+fn main() {
+}