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,
cmt: mc::cmt) -> bool {
match cmt.cat {
mc::cat_stack_upvar(*) |
mc::cat_implicit_self(*) |
mc::cat_copied_upvar(*) |
mc::cat_deref(_, _, mc::region_ptr(*)) |
mc::cat_deref(_, _, mc::gc_ptr(*)) |
mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
@ -114,6 +112,24 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
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,
// but what happens in practice is that you have a
// reference to a constant with a type that should be

View File

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