librustc: Automatically move non-implicitly-copyable types into unique closures. r=nmatsakis
This commit is contained in:
parent
7ca94369da
commit
45848b2040
@ -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});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
_ => {
|
||||
|
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let x = ~"Hello world!";
|
||||
do task::spawn {
|
||||
io::println(x);
|
||||
}
|
||||
io::println(x); //~ ERROR use of moved variable
|
||||
}
|
||||
|
7
src/test/run-pass/moves-based-on-type-capture-clause.rs
Normal file
7
src/test/run-pass/moves-based-on-type-capture-clause.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
let x = ~"Hello world!";
|
||||
do task::spawn {
|
||||
io::println(x);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user