Skip to content

Commit 1b9f740

Browse files
committed
librustc: Reset the mode context to MoveValue for block lambdas. rs=bugfix
1 parent 4559895 commit 1b9f740

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

src/librustc/middle/mode.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,27 @@ struct VisitContext {
3232

3333
fn compute_modes_for_fn_args(callee_id: node_id,
3434
args: &[@expr],
35+
last_arg_is_block: bool,
3536
&&cx: VisitContext,
3637
v: vt<VisitContext>) {
3738
let arg_tys = ty::ty_fn_args(ty::node_id_to_type(cx.tcx, callee_id));
39+
let mut i = 0;
3840
for vec::each2(args, arg_tys) |arg, arg_ty| {
39-
match ty::resolved_mode(cx.tcx, arg_ty.mode) {
40-
by_ref => {
41-
let arg_cx = VisitContext { mode: ReadValue, ..cx };
42-
compute_modes_for_expr(*arg, arg_cx, v);
41+
if last_arg_is_block && i == args.len() - 1 {
42+
let block_cx = VisitContext { mode: MoveValue, ..cx };
43+
compute_modes_for_expr(*arg, block_cx, v);
44+
} else {
45+
match ty::resolved_mode(cx.tcx, arg_ty.mode) {
46+
by_ref => {
47+
let arg_cx = VisitContext { mode: ReadValue, ..cx };
48+
compute_modes_for_expr(*arg, arg_cx, v);
49+
}
50+
by_val | by_move | by_copy => {
51+
compute_modes_for_expr(*arg, cx, v);
52+
}
4353
}
44-
by_val | by_move | by_copy => compute_modes_for_expr(*arg, cx, v)
4554
}
55+
i += 1;
4656
}
4757
}
4858

@@ -80,10 +90,10 @@ fn compute_modes_for_expr(expr: @expr,
8090
};
8191

8292
match expr.node {
83-
expr_call(callee, args, _) => {
93+
expr_call(callee, args, is_block) => {
8494
let callee_cx = VisitContext { mode: ReadValue, ..cx };
8595
compute_modes_for_expr(callee, callee_cx, v);
86-
compute_modes_for_fn_args(callee.id, args, cx, v);
96+
compute_modes_for_fn_args(callee.id, args, is_block, cx, v);
8797
}
8898
expr_path(*) => {
8999
record_mode_for_expr(expr, cx);
@@ -92,7 +102,7 @@ fn compute_modes_for_expr(expr: @expr,
92102
let callee_cx = VisitContext { mode: CopyValue, ..cx };
93103
compute_modes_for_expr(expr, callee_cx, v);
94104
}
95-
expr_method_call(callee, _, _, args, _) => {
105+
expr_method_call(callee, _, _, args, is_block) => {
96106
// The LHS of the dot may or may not result in a move, depending
97107
// on the method map entry.
98108
let callee_mode;
@@ -111,7 +121,7 @@ fn compute_modes_for_expr(expr: @expr,
111121
let callee_cx = VisitContext { mode: callee_mode, ..cx };
112122
compute_modes_for_expr(callee, callee_cx, v);
113123

114-
compute_modes_for_fn_args(expr.callee_id, args, cx, v);
124+
compute_modes_for_fn_args(expr.callee_id, args, is_block, cx, v);
115125
}
116126
expr_binary(_, lhs, rhs) | expr_assign_op(_, lhs, rhs) => {
117127
// The signatures of these take their arguments by-ref, so they
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
struct S {
2+
x: ~E
3+
}
4+
5+
enum E {
6+
Foo(~S),
7+
Bar(~int),
8+
Baz
9+
}
10+
11+
fn f(s: &S, g: &fn(&S)) {
12+
g(s)
13+
}
14+
15+
fn main() {
16+
let s = S { x: ~Bar(~42) };
17+
loop {
18+
do f(&s) |hellothere| {
19+
match hellothere.x { //~ ERROR moving out of immutable field
20+
~Foo(_) => {}
21+
~Bar(x) => io::println(x.to_str()),
22+
~Baz => {}
23+
}
24+
}
25+
}
26+
}
27+

0 commit comments

Comments
 (0)