Skip to content

Commit 8a9df5a

Browse files
committed
make it illegal to implicitly capture mutable variables
this is the final part of #1273
1 parent d709ed2 commit 8a9df5a

32 files changed

+259
-123
lines changed

src/librustsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ type capture_item = {
362362
};
363363

364364
#[auto_serialize]
365-
type capture_clause = [capture_item];
365+
type capture_clause = @[capture_item];
366366

367367
/*
368368
// Says whether this is a block the user marked as

src/librustsyntax/parse/parser.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,8 @@ fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
11871187

11881188
let body = parse_block(p);
11891189
ret mk_expr(p, lo, body.span.hi,
1190-
ast::expr_fn(proto, decl, body, capture_clause + cc_old));
1190+
ast::expr_fn(proto, decl, body,
1191+
@(*capture_clause + cc_old)));
11911192
}
11921193

11931194
fn parse_fn_block_expr(p: parser) -> @ast::expr {
@@ -1679,7 +1680,7 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] {
16791680
}
16801681

16811682
// FIXME Remove after snapshot
1682-
fn parse_old_skool_capture_clause(p: parser) -> ast::capture_clause {
1683+
fn parse_old_skool_capture_clause(p: parser) -> [ast::capture_item] {
16831684
fn expect_opt_trailing_semi(p: parser) {
16841685
if !eat(p, token::SEMI) {
16851686
if p.token != token::RBRACKET {
@@ -1739,7 +1740,7 @@ fn parse_fn_decl(p: parser, purity: ast::purity,
17391740
parse_arg_fn, p).node;
17401741

17411742
let inputs = either::lefts(args_or_capture_items);
1742-
let capture_clause = either::rights(args_or_capture_items);
1743+
let capture_clause = @either::rights(args_or_capture_items);
17431744

17441745
// Use the args list to translate each bound variable
17451746
// mentioned in a constraint to an arg index.
@@ -1778,7 +1779,7 @@ fn parse_fn_block_decl(p: parser) -> (ast::fn_decl, ast::capture_clause) {
17781779
purity: ast::impure_fn,
17791780
cf: ast::return_val,
17801781
constraints: []},
1781-
either::rights(inputs_captures));
1782+
@either::rights(inputs_captures));
17821783
}
17831784

17841785
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {

src/librustsyntax/print/pprust.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
10181018
// head-box, will be closed by print-block at start
10191019
ibox(s, 0u);
10201020
word(s.s, proto_to_str(proto));
1021-
print_fn_args_and_ret(s, decl, cap_clause);
1021+
print_fn_args_and_ret(s, decl, *cap_clause);
10221022
space(s.s);
10231023
print_block(s, body);
10241024
}
@@ -1028,7 +1028,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
10281028
// head-box, will be closed by print-block at start
10291029
ibox(s, 0u);
10301030
word(s.s, "{");
1031-
print_fn_block_args(s, decl, cap_clause);
1031+
print_fn_block_args(s, decl, *cap_clause);
10321032
print_possibly_embedded_block(s, body, block_block_fn, indent_unit);
10331033
}
10341034
ast::expr_loop_body(body) {

src/librustsyntax/visit.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ enum fn_kind {
1616
fk_item_fn(ident, [ty_param]), //< an item declared with fn()
1717
fk_method(ident, [ty_param], @method),
1818
fk_res(ident, [ty_param], region_param),
19-
fk_anon(proto), //< an anonymous function like fn@(...)
20-
fk_fn_block, //< a block {||...}
19+
fk_anon(proto, capture_clause), //< an anonymous function like fn@(...)
20+
fk_fn_block(capture_clause), //< a block {||...}
2121
fk_ctor(ident, [ty_param], node_id /* self id */,
2222
def_id /* parent class id */) // class constructor
2323
}
@@ -26,15 +26,15 @@ fn name_of_fn(fk: fn_kind) -> ident {
2626
alt fk {
2727
fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _, _)
2828
| fk_ctor(name, _, _, _) { name }
29-
fk_anon(_) | fk_fn_block { "anon" }
29+
fk_anon(*) | fk_fn_block(*) { "anon" }
3030
}
3131
}
3232

3333
fn tps_of_fn(fk: fn_kind) -> [ty_param] {
3434
alt fk {
3535
fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps, _)
3636
| fk_ctor(_, tps, _, _) { tps }
37-
fk_anon(_) | fk_fn_block { [] }
37+
fk_anon(*) | fk_fn_block(*) { [] }
3838
}
3939
}
4040

@@ -381,11 +381,13 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
381381
v.visit_expr(x, e, v);
382382
for arms.each {|a| v.visit_arm(a, e, v); }
383383
}
384-
expr_fn(proto, decl, body, _) {
385-
v.visit_fn(fk_anon(proto), decl, body, ex.span, ex.id, e, v);
384+
expr_fn(proto, decl, body, cap_clause) {
385+
v.visit_fn(fk_anon(proto, cap_clause), decl, body,
386+
ex.span, ex.id, e, v);
386387
}
387-
expr_fn_block(decl, body, _) {
388-
v.visit_fn(fk_fn_block, decl, body, ex.span, ex.id, e, v);
388+
expr_fn_block(decl, body, cap_clause) {
389+
v.visit_fn(fk_fn_block(cap_clause), decl, body,
390+
ex.span, ex.id, e, v);
389391
}
390392
expr_block(b) { v.visit_block(b, e, v); }
391393
expr_assign(a, b) { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }

src/rustc/front/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ fn mk_test_wrapper(cx: test_ctxt,
368368
let wrapper_expr: ast::expr = {
369369
id: cx.sess.next_node_id(),
370370
node: ast::expr_fn(ast::proto_bare, wrapper_decl,
371-
wrapper_body, []),
371+
wrapper_body, @[]),
372372
span: span
373373
};
374374

src/rustc/metadata/astencode.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,7 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
223223
vfn(m.self_id);
224224
vec::iter(tps) {|tp| vfn(tp.id)}
225225
}
226-
visit::fk_anon(_) |
227-
visit::fk_fn_block {
226+
visit::fk_anon(*) | visit::fk_fn_block(*) {
228227
}
229228
}
230229

src/rustc/middle/capture.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ type capture_map = map::hashmap<ast::def_id, capture_var>;
3131
// errors for any irregularities which we identify.
3232
fn check_capture_clause(tcx: ty::ctxt,
3333
fn_expr_id: ast::node_id,
34-
fn_proto: ast::proto,
3534
cap_clause: ast::capture_clause) {
3635
let freevars = freevars::get_freevars(tcx, fn_expr_id);
3736
let seen_defs = map::int_hash();
3837

39-
let check_capture_item = fn@(cap_item: ast::capture_item) {
38+
for (*cap_clause).each { |cap_item|
4039
let cap_def = tcx.def_map.get(cap_item.id);
4140
if !vec::any(*freevars, {|fv| fv.def == cap_def}) {
4241
tcx.sess.span_warn(
@@ -52,22 +51,6 @@ fn check_capture_clause(tcx: ty::ctxt,
5251
#fmt("variable '%s' captured more than once",
5352
cap_item.name));
5453
}
55-
};
56-
57-
alt fn_proto {
58-
ast::proto_any | ast::proto_block {
59-
if vec::is_not_empty(cap_clause) {
60-
let cap_item0 = vec::head(cap_clause);
61-
tcx.sess.span_err(
62-
cap_item0.span,
63-
"cannot capture values explicitly with a block closure");
64-
}
65-
}
66-
ast::proto_bare | ast::proto_box | ast::proto_uniq {
67-
for cap_clause.each { |cap_item|
68-
check_capture_item(cap_item);
69-
}
70-
}
7154
}
7255
}
7356

@@ -80,7 +63,7 @@ fn compute_capture_vars(tcx: ty::ctxt,
8063

8164
// first add entries for anything explicitly named in the cap clause
8265

83-
for cap_clause.each { |cap_item|
66+
for (*cap_clause).each { |cap_item|
8467
let cap_def = tcx.def_map.get(cap_item.id);
8568
let cap_def_id = ast_util::def_id_of_def(cap_def).node;
8669
if cap_item.is_move {

0 commit comments

Comments
 (0)