about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-12-20 19:39:33 -0800
committerNiko Matsakis <niko@alum.mit.edu>2011-12-21 06:14:36 -0800
commitc03d14a33ddee8001f59224b40ce2fe06a71e074 (patch)
treef45f2b05cff24b608794ab3c880d3bae1d018b31
parent01cb1044f74b69e128bd73651971ef365954a0ba (diff)
downloadrust-c03d14a33ddee8001f59224b40ce2fe06a71e074.tar.gz
rust-c03d14a33ddee8001f59224b40ce2fe06a71e074.zip
upgrade kind check
-rw-r--r--src/comp/middle/kind.rs64
-rw-r--r--src/comp/syntax/visit.rs1
2 files changed, 53 insertions, 12 deletions
diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs
index d07e862ceb9..88a763fb638 100644
--- a/src/comp/middle/kind.rs
+++ b/src/comp/middle/kind.rs
@@ -42,7 +42,8 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
                last_uses: last_uses};
     let visit = visit::mk_vt(@{
         visit_expr: check_expr,
-        visit_stmt: check_stmt
+        visit_stmt: check_stmt,
+        visit_fn_body: check_fn_body
         with *visit::default_visitor()
     });
     visit::visit_crate(*crate, ctx, visit);
@@ -50,18 +51,61 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
     ret ctx.rval_map;
 }
 
-fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
+// Yields the appropriate function to check the kind of closed over
+// variables. `id` is the node_id for some expression that creates the
+// closure.
+fn with_closure_check_fn(cx: ctx, id: node_id,
+                         b: block(fn(ctx, ty::t, sp: span))) {
+    let fty = ty::node_id_to_monotype(cx.tcx, id);
+    alt ty::ty_fn_proto(cx.tcx, fty) {
+      proto_send. { b(check_send); }
+      proto_shared(_) { b(check_copy); }
+      proto_block. | proto_bare. { /* no check needed */ }
+    }
+}
+
+// Check that the free variables used in a shared/sendable closure conform
+// to the copy/move kind bounds. Then recursively check the function body.
+fn check_fn_body(decl: fn_decl, body: blk, sp: span, i: fn_ident, id: node_id,
+                 cx: ctx, v: visit::vt<ctx>) {
 
-    fn check_free_vars(e: @expr,
-                       cx: ctx,
-                       check_fn: fn(ctx, ty::t, sp: span)) {
-        for @{def, span} in *freevars::get_freevars(cx.tcx, e.id) {
+    // n.b.: This could be the body of either a fn decl or a fn expr.  In the
+    // former case, the prototype will be proto_bare and no check occurs.  In
+    // the latter case, we do not check the variables that in the capture
+    // clause (as we don't have access to that here) but just those that
+    // appear free.  The capture clauses are checked below, in check_expr().
+    //
+    // We could do this check also in check_expr(), but it seems more
+    // "future-proof" to do it this way, as check_fn_body() is supposed to be
+    // the common flow point for all functions that appear in the AST.
+
+    with_closure_check_fn(cx, id) { |check_fn|
+        for @{def, span} in *freevars::get_freevars(cx.tcx, 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, span);
         }
     }
 
+    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_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
+
     alt e.node {
       expr_assign(_, ex) | expr_assign_op(_, _, ex) |
       expr_block({node: {expr: some(ex), _}, _}) |
@@ -121,13 +165,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
           none. {}
         }
       }
-      expr_fn({proto: proto_send., _}, captures) { // NDM captures
-        check_free_vars(e, cx, check_send);
-      }
-      expr_fn({proto: proto_shared(_), _}, captures) { // NDM captures
-        check_free_vars(e, cx, check_copy);
-      }
       expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); }
+      expr_fn(_, cap_clause) { check_fn_cap_clause(cx, e.id, *cap_clause); }
+
       _ { }
     }
     visit::visit_expr(e, cx, v);
diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs
index 3f0d7a27a51..be3769a4ba1 100644
--- a/src/comp/syntax/visit.rs
+++ b/src/comp/syntax/visit.rs
@@ -39,6 +39,7 @@ type visitor<E> =
       visit_fn_block: fn@(fn_decl, blk, span, node_id, E, vt<E>),
 
       // Invoked by both visit_fn_proto and visit_fn_block above.
+      // Intended to be a common flow point for all fn decls in AST.
       visit_fn_body: fn@(fn_decl, blk, span, fn_ident, node_id, E, vt<E>)};
 
 fn default_visitor<E>() -> visitor<E> {