Permit moving out of captured upvars in once fns. Close #2549.

This commit is contained in:
Ben Blum 2013-06-17 19:06:36 -04:00
parent 2c7903d599
commit 1496216db6
2 changed files with 23 additions and 7 deletions

View File

@ -101,9 +101,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
cmt0: mc::cmt, cmt0: mc::cmt,
cmt: mc::cmt) -> bool { cmt: mc::cmt) -> bool {
match cmt.cat { match cmt.cat {
mc::cat_stack_upvar(*) |
mc::cat_implicit_self(*) | mc::cat_implicit_self(*) |
mc::cat_copied_upvar(*) |
mc::cat_deref(_, _, mc::region_ptr(*)) | mc::cat_deref(_, _, mc::region_ptr(*)) |
mc::cat_deref(_, _, mc::gc_ptr(*)) | mc::cat_deref(_, _, mc::gc_ptr(*)) |
mc::cat_deref(_, _, mc::unsafe_ptr(*)) => { mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
@ -114,6 +112,24 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
false false
} }
// These are separate from the above cases for a better error message.
mc::cat_stack_upvar(*) |
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, _ }) => {
bccx.span_err(
cmt0.span,
fmt!("cannot move out of %s \
(unless the destination closure type is `once fn')",
bccx.cmt_to_str(cmt)));
false
}
// Can move out of captured upvars only if the destination closure
// type is 'once'. 1-shot stack closures emit the copied_upvar form
// (see mem_categorization.rs).
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, _ }) => {
true
}
// It seems strange to allow a move out of a static item, // It seems strange to allow a move out of a static item,
// but what happens in practice is that you have a // but what happens in practice is that you have a
// reference to a constant with a type that should be // reference to a constant with a type that should be

View File

@ -78,7 +78,7 @@ pub enum categorization {
} }
#[deriving(Eq)] #[deriving(Eq)]
struct CopiedUpvar { pub struct CopiedUpvar {
upvar_id: ast::node_id, upvar_id: ast::node_id,
onceness: ast::Onceness, onceness: ast::Onceness,
} }
@ -497,9 +497,8 @@ impl mem_categorization_ctxt {
let ty = ty::node_id_to_type(self.tcx, fn_node_id); let ty = ty::node_id_to_type(self.tcx, fn_node_id);
match ty::get(ty).sty { match ty::get(ty).sty {
ty::ty_closure(ref closure_ty) => { ty::ty_closure(ref closure_ty) => {
let sigil = closure_ty.sigil; match (closure_ty.sigil, closure_ty.onceness) {
match sigil { (ast::BorrowedSigil, ast::Many) => {
ast::BorrowedSigil => {
let upvar_cmt = let upvar_cmt =
self.cat_def(id, span, expr_ty, *inner); self.cat_def(id, span, expr_ty, *inner);
@cmt_ { @cmt_ {
@ -510,7 +509,8 @@ impl mem_categorization_ctxt {
ty:upvar_cmt.ty ty:upvar_cmt.ty
} }
} }
ast::OwnedSigil | ast::ManagedSigil => { (ast::BorrowedSigil, ast::Once) |
(ast::OwnedSigil, _) | (ast::ManagedSigil, _) => {
// FIXME #2152 allow mutation of moved upvars // FIXME #2152 allow mutation of moved upvars
@cmt_ { @cmt_ {
id:id, id:id,