Skip to content

Commit 1496216

Browse files
committed
Permit moving out of captured upvars in once fns. Close #2549.
1 parent 2c7903d commit 1496216

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

Diff for: src/librustc/middle/borrowck/gather_loans/gather_moves.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
101101
cmt0: mc::cmt,
102102
cmt: mc::cmt) -> bool {
103103
match cmt.cat {
104-
mc::cat_stack_upvar(*) |
105104
mc::cat_implicit_self(*) |
106-
mc::cat_copied_upvar(*) |
107105
mc::cat_deref(_, _, mc::region_ptr(*)) |
108106
mc::cat_deref(_, _, mc::gc_ptr(*)) |
109107
mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
@@ -114,6 +112,24 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
114112
false
115113
}
116114

115+
// These are separate from the above cases for a better error message.
116+
mc::cat_stack_upvar(*) |
117+
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, _ }) => {
118+
bccx.span_err(
119+
cmt0.span,
120+
fmt!("cannot move out of %s \
121+
(unless the destination closure type is `once fn')",
122+
bccx.cmt_to_str(cmt)));
123+
false
124+
}
125+
126+
// Can move out of captured upvars only if the destination closure
127+
// type is 'once'. 1-shot stack closures emit the copied_upvar form
128+
// (see mem_categorization.rs).
129+
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, _ }) => {
130+
true
131+
}
132+
117133
// It seems strange to allow a move out of a static item,
118134
// but what happens in practice is that you have a
119135
// reference to a constant with a type that should be

Diff for: src/librustc/middle/mem_categorization.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub enum categorization {
7878
}
7979

8080
#[deriving(Eq)]
81-
struct CopiedUpvar {
81+
pub struct CopiedUpvar {
8282
upvar_id: ast::node_id,
8383
onceness: ast::Onceness,
8484
}
@@ -497,9 +497,8 @@ impl mem_categorization_ctxt {
497497
let ty = ty::node_id_to_type(self.tcx, fn_node_id);
498498
match ty::get(ty).sty {
499499
ty::ty_closure(ref closure_ty) => {
500-
let sigil = closure_ty.sigil;
501-
match sigil {
502-
ast::BorrowedSigil => {
500+
match (closure_ty.sigil, closure_ty.onceness) {
501+
(ast::BorrowedSigil, ast::Many) => {
503502
let upvar_cmt =
504503
self.cat_def(id, span, expr_ty, *inner);
505504
@cmt_ {
@@ -510,7 +509,8 @@ impl mem_categorization_ctxt {
510509
ty:upvar_cmt.ty
511510
}
512511
}
513-
ast::OwnedSigil | ast::ManagedSigil => {
512+
(ast::BorrowedSigil, ast::Once) |
513+
(ast::OwnedSigil, _) | (ast::ManagedSigil, _) => {
514514
// FIXME #2152 allow mutation of moved upvars
515515
@cmt_ {
516516
id:id,

0 commit comments

Comments
 (0)