rustc: Prevent repeated moves out of proc upvars

This fixes the categorization of the upvars of procs (represented internally
as once fns) to consider usage to require a loan. In doing so, upvars are no
longer allowed to be moved out of repeatedly in loops and such.

Closes #10398
Closes #12041
Closes #12127
This commit is contained in:
Alex Crichton 2014-04-08 16:59:18 -07:00
parent 02f51211ed
commit 767ed1a71f
5 changed files with 61 additions and 2 deletions

View File

@ -274,12 +274,13 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
match cmt.cat {
mc::cat_rvalue(..) |
mc::cat_static_item |
mc::cat_copied_upvar(_) => {
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
None
}
mc::cat_local(id) |
mc::cat_arg(id) |
mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => {
Some(@LpVar(id))
}

View File

@ -0,0 +1,19 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let x = ~1;
let f: proc() = proc() {
let _a = x;
drop(x);
//~^ ERROR: use of moved value: `x`
};
f();
}

View File

@ -11,7 +11,7 @@
fn main() {
let r = {
let x = ~42;
let f = proc() &x; //~ ERROR: borrowed value does not live long enough
let f = proc() &x; //~ ERROR: `x` does not live long enough
f()
};

View File

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let (tx, rx) = channel();
spawn(proc() {
loop {
let tx = tx;
//~^ ERROR: use of moved value: `tx`
tx.send(1);
}
});
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let f = proc() {};
(proc() {
f();
f();
//~^ ERROR: use of moved value: `f`
})()
}