diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 5431a0a2998..d982be684a2 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -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 diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 14764e7bc37..d020cf651a4 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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,