Skip to content

Commit

Permalink
Consume once fns when calling them (rust-lang#2549).
Browse files Browse the repository at this point in the history
  • Loading branch information
bblum committed Jun 19, 2013
1 parent 1120f8c commit 2c7903d
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/librustc/middle/moves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ struct VisitContext {
move_maps: MoveMaps
}

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

expr_call(callee, ref args, _) => { // callee(args)
self.use_expr(callee, Read, visitor);
// Figure out whether the called function is consumed.
let mode = match ty::get(ty::expr_ty(self.tcx, callee)).sty {
ty::ty_closure(ref cty) => {
match cty.onceness {
Once => Move,
Many => Read,
}
},
ty::ty_bare_fn(*) => Read,
ref x =>
self.tcx.sess.span_bug(callee.span,
fmt!("non-function type in moves for expr_call: %?", x)),
};
// Note we're not using consume_expr, which uses type_moves_by_default
// to determine the mode, for this. The reason is that while stack
// closures should be noncopyable, they shouldn't move by default;
// calling a closure should only consume it if it's once.

This comment has been minimized.

Copy link
@nikomatsakis

nikomatsakis Jun 22, 2013

I don't quite understand this comment. type_moves_by_default should be true (and is true, afaik) for once closures. If it were not true, one could copy once closures, which would tend to defeat the purpose of them. So it seems like you could invoke consume if once or use(read) if many, which is how the rest of the code works.

This comment has been minimized.

Copy link
@bblum

bblum Jun 22, 2013

Author Owner

Oh, the phrasing "stack closures should be noncopyable" is confusing. What I mean is that all stack closures are noncopyable (recurring closure, etc), but only once fns should be consumed when called. If I called type_moves_by_default here, that would cause non-once fns to be consumed when called as well (well, not yet, but when the recurring closure bug gets fixed, it would).

if mode == Move {
self.move_maps.moves_map.insert(callee.id);
}
self.use_expr(callee, mode, visitor);
self.use_fn_args(callee.id, *args, visitor);
}

Expand Down

0 comments on commit 2c7903d

Please sign in to comment.