librustc: Automatically move non-implicitly-copyable types into unique closures. r=nmatsakis

This commit is contained in:
Patrick Walton 2012-12-10 13:59:51 -08:00
parent 7ca94369da
commit 45848b2040
7 changed files with 45 additions and 23 deletions

View File

@ -110,22 +110,29 @@ fn compute_capture_vars(tcx: ty::ctxt,
// now go through anything that is referenced but was not explicitly
// named and add that
let implicit_mode;
if fn_proto == ast::ProtoBorrowed {
implicit_mode = cap_ref;
} else {
implicit_mode = cap_copy;
}
let implicit_mode_is_by_ref = fn_proto == ast::ProtoBorrowed;
for vec::each(*freevars) |fvar| {
let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
match cap_map.find(fvar_def_id) {
option::Some(_) => { /* was explicitly named, do nothing */ }
option::None => {
// Move if this type implicitly moves; copy otherwise.
let mode;
if implicit_mode_is_by_ref {
mode = cap_ref;
} else {
let fvar_ty = ty::node_id_to_type(tcx, fvar_def_id);
if ty::type_implicitly_moves(tcx, fvar_ty) {
mode = cap_move;
} else {
mode = cap_copy;
}
};
cap_map.insert(fvar_def_id, {def:fvar.def,
span: fvar.span,
cap_item: None,
mode:implicit_mode});
mode:mode});
}
}
}

View File

@ -201,7 +201,6 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
let cap_def = cx.tcx.def_map.get(cap_item.id);
let cap_def_id = ast_util::def_id_of_def(cap_def).node;
let ty = ty::node_id_to_type(cx.tcx, cap_def_id);
// Here's where is_move isn't always false...
chk(cx, fn_id, None, cap_item.is_move, ty, cap_item.span);
cap_def_id
};
@ -215,9 +214,12 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
if captured_vars.contains(&id) { loop; }
let ty = ty::node_id_to_type(cx.tcx, id);
// is_move is always false here. See the let captured_vars...
// code above for where it's not always false.
chk(cx, fn_id, Some(*fv), false, ty, fv.span);
// is_move is true if this type implicitly moves and false
// otherwise.
let is_move = ty::type_implicitly_moves(cx.tcx, ty);
chk(cx, fn_id, Some(*fv), is_move, ty, fv.span);
}
}

View File

@ -524,8 +524,8 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
// in better error messages than just pointing at the closure
// construction site.
let proto = ty::ty_fn_proto(ty::expr_ty(self.tcx, expr));
let cvs = capture::compute_capture_vars(self.tcx, expr.id,
proto, cap_clause);
let cvs = capture::compute_capture_vars(self.tcx, expr.id, proto,
cap_clause);
let mut call_caps = ~[];
for cvs.each |cv| {
match relevant_def(cv.def) {

View File

@ -621,8 +621,8 @@ fn trans_arg_expr(bcx: block,
let arg_ty = expr_ty(bcx, arg_expr);
let proto = ty::ty_fn_proto(arg_ty);
let bcx = closure::trans_expr_fn(
bcx, proto, decl, (*body), blk.id,
cap, Some(ret_flag), expr::SaveIn(scratch));
bcx, proto, decl, (*body), blk.id, cap,
Some(ret_flag), expr::SaveIn(scratch));
DatumBlock {bcx: bcx,
datum: Datum {val: scratch,
ty: scratch_ty,

View File

@ -549,9 +549,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
ast::expr_fn(proto, decl, ref body, cap_clause) => {
// Don't use this function for anything real. Use the one in
// astconv instead.
return closure::trans_expr_fn(bcx, proto,
decl, (*body), expr.id, cap_clause,
None, dest);
return closure::trans_expr_fn(bcx, proto, decl, *body, expr.id,
cap_clause, None, dest);
}
ast::expr_fn_block(decl, ref body, cap_clause) => {
let expr_ty = expr_ty(bcx, expr);
@ -561,9 +560,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
expr_to_str(expr, tcx.sess.intr()),
ty_to_str(tcx, expr_ty));
return closure::trans_expr_fn(
bcx, fn_ty.meta.proto, decl, (*body),
expr.id, cap_clause, None,
dest);
bcx, fn_ty.meta.proto, decl, *body, expr.id,
cap_clause, None, dest);
}
_ => {
bcx.sess().impossible_case(
@ -577,7 +575,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
match blk.node {
ast::expr_fn_block(decl, ref body, cap) => {
return closure::trans_expr_fn(
bcx, fn_ty.meta.proto, decl, (*body), blk.id,
bcx, fn_ty.meta.proto, decl, *body, blk.id,
cap, Some(None), dest);
}
_ => {

View File

@ -0,0 +1,8 @@
fn main() {
let x = ~"Hello world!";
do task::spawn {
io::println(x);
}
io::println(x); //~ ERROR use of moved variable
}

View File

@ -0,0 +1,7 @@
fn main() {
let x = ~"Hello world!";
do task::spawn {
io::println(x);
}
}