Skip to content

Commit 9d42f2d

Browse files
committed
---
yaml --- r: 6903 b: refs/heads/master c: c03d14a h: refs/heads/master i: 6901: c7f1cdb 6899: 57c2085 6895: 490000c v: v3
1 parent a4bcf6b commit 9d42f2d

File tree

3 files changed

+54
-13
lines changed

3 files changed

+54
-13
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 01cb1044f74b69e128bd73651971ef365954a0ba
2+
refs/heads/master: c03d14a33ddee8001f59224b40ce2fe06a71e074

trunk/src/comp/middle/kind.rs

+52-12
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,70 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
4242
last_uses: last_uses};
4343
let visit = visit::mk_vt(@{
4444
visit_expr: check_expr,
45-
visit_stmt: check_stmt
45+
visit_stmt: check_stmt,
46+
visit_fn_body: check_fn_body
4647
with *visit::default_visitor()
4748
});
4849
visit::visit_crate(*crate, ctx, visit);
4950
tcx.sess.abort_if_errors();
5051
ret ctx.rval_map;
5152
}
5253

53-
fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
54+
// Yields the appropriate function to check the kind of closed over
55+
// variables. `id` is the node_id for some expression that creates the
56+
// closure.
57+
fn with_closure_check_fn(cx: ctx, id: node_id,
58+
b: block(fn(ctx, ty::t, sp: span))) {
59+
let fty = ty::node_id_to_monotype(cx.tcx, id);
60+
alt ty::ty_fn_proto(cx.tcx, fty) {
61+
proto_send. { b(check_send); }
62+
proto_shared(_) { b(check_copy); }
63+
proto_block. | proto_bare. { /* no check needed */ }
64+
}
65+
}
66+
67+
// Check that the free variables used in a shared/sendable closure conform
68+
// to the copy/move kind bounds. Then recursively check the function body.
69+
fn check_fn_body(decl: fn_decl, body: blk, sp: span, i: fn_ident, id: node_id,
70+
cx: ctx, v: visit::vt<ctx>) {
5471

55-
fn check_free_vars(e: @expr,
56-
cx: ctx,
57-
check_fn: fn(ctx, ty::t, sp: span)) {
58-
for @{def, span} in *freevars::get_freevars(cx.tcx, e.id) {
72+
// n.b.: This could be the body of either a fn decl or a fn expr. In the
73+
// former case, the prototype will be proto_bare and no check occurs. In
74+
// the latter case, we do not check the variables that in the capture
75+
// clause (as we don't have access to that here) but just those that
76+
// appear free. The capture clauses are checked below, in check_expr().
77+
//
78+
// We could do this check also in check_expr(), but it seems more
79+
// "future-proof" to do it this way, as check_fn_body() is supposed to be
80+
// the common flow point for all functions that appear in the AST.
81+
82+
with_closure_check_fn(cx, id) { |check_fn|
83+
for @{def, span} in *freevars::get_freevars(cx.tcx, id) {
5984
let id = ast_util::def_id_of_def(def).node;
6085
let ty = ty::node_id_to_type(cx.tcx, id);
6186
check_fn(cx, ty, span);
6287
}
6388
}
6489

90+
visit::visit_fn_body(decl, body, sp, i, id, cx, v);
91+
}
92+
93+
fn check_fn_cap_clause(_cx: ctx,
94+
_id: node_id,
95+
_cap_clause: capture_clause) {
96+
// let freevars = freevars::get_freevars(cx.tcx, i);
97+
// let contains_var = lambda(id: def_id) -> bool {
98+
// vec::any(freevars, { |freevar|
99+
// ast_util::def_id_of_def(freevar).node == def_id
100+
// })
101+
// }
102+
// with_closure_check_fn(cx, id) { |check_fn|
103+
// let check_var = lambda(
104+
// }
105+
}
106+
107+
fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
108+
65109
alt e.node {
66110
expr_assign(_, ex) | expr_assign_op(_, _, ex) |
67111
expr_block({node: {expr: some(ex), _}, _}) |
@@ -121,13 +165,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
121165
none. {}
122166
}
123167
}
124-
expr_fn({proto: proto_send., _}, captures) { // NDM captures
125-
check_free_vars(e, cx, check_send);
126-
}
127-
expr_fn({proto: proto_shared(_), _}, captures) { // NDM captures
128-
check_free_vars(e, cx, check_copy);
129-
}
130168
expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); }
169+
expr_fn(_, cap_clause) { check_fn_cap_clause(cx, e.id, *cap_clause); }
170+
131171
_ { }
132172
}
133173
visit::visit_expr(e, cx, v);

trunk/src/comp/syntax/visit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type visitor<E> =
3939
visit_fn_block: fn@(fn_decl, blk, span, node_id, E, vt<E>),
4040

4141
// Invoked by both visit_fn_proto and visit_fn_block above.
42+
// Intended to be a common flow point for all fn decls in AST.
4243
visit_fn_body: fn@(fn_decl, blk, span, fn_ident, node_id, E, vt<E>)};
4344

4445
fn default_visitor<E>() -> visitor<E> {

0 commit comments

Comments
 (0)