Skip to content

Commit 2c7903d

Browse files
committed
Consume once fns when calling them (rust-lang#2549).
1 parent 1120f8c commit 2c7903d

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

src/librustc/middle/moves.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ struct VisitContext {
183183
move_maps: MoveMaps
184184
}
185185

186+
#[deriving(Eq)]
186187
enum UseMode {
187188
Move, // This value or something owned by it is moved.
188189
Read // Read no matter what the type.
@@ -335,7 +336,27 @@ impl VisitContext {
335336
}
336337

337338
expr_call(callee, ref args, _) => { // callee(args)
338-
self.use_expr(callee, Read, visitor);
339+
// Figure out whether the called function is consumed.
340+
let mode = match ty::get(ty::expr_ty(self.tcx, callee)).sty {
341+
ty::ty_closure(ref cty) => {
342+
match cty.onceness {
343+
Once => Move,
344+
Many => Read,
345+
}
346+
},
347+
ty::ty_bare_fn(*) => Read,
348+
ref x =>
349+
self.tcx.sess.span_bug(callee.span,
350+
fmt!("non-function type in moves for expr_call: %?", x)),
351+
};
352+
// Note we're not using consume_expr, which uses type_moves_by_default
353+
// to determine the mode, for this. The reason is that while stack
354+
// closures should be noncopyable, they shouldn't move by default;
355+
// calling a closure should only consume it if it's once.
356+
if mode == Move {
357+
self.move_maps.moves_map.insert(callee.id);
358+
}
359+
self.use_expr(callee, mode, visitor);
339360
self.use_fn_args(callee.id, *args, visitor);
340361
}
341362

0 commit comments

Comments
 (0)