Auto merge of #21604 - nikomatsakis:closure-move-indiv-vars, r=eddyb

r? @eddyb
This commit is contained in:
bors 2015-01-30 15:32:27 +00:00
commit 3fbfad3519
30 changed files with 644 additions and 480 deletions

View file

@ -58,8 +58,10 @@ fn test6() {
fn test7() {
fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
let mut f = |&mut: g: Box<FnMut(isize)>, b: isize| {};
f(box |a| { //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
foo(f); //~ ERROR: cannot move out of captured outer variable
f(box |a| {
foo(f);
//~^ ERROR cannot move `f` into closure because it is borrowed
//~| ERROR cannot move out of captured outer variable in an `FnMut` closure
}, 3);
}

View file

@ -19,24 +19,24 @@ fn main() {
// By-ref cases
{
let x = box 0us;
let f = |&:| drop(x); //~ cannot move
let f = |&:| drop(x); //~ ERROR cannot move
}
{
let x = box 0us;
let f = |&mut:| drop(x); //~ cannot move
let f = |&mut:| drop(x); //~ ERROR cannot move
}
{
let x = box 0us;
let f = |:| drop(x); //~ cannot move
let f = |:| drop(x); // OK -- FnOnce
}
// By-value cases
{
let x = box 0us;
let f = move |&:| drop(x); //~ cannot move
let f = move |&:| drop(x); //~ ERROR cannot move
}
{
let x = box 0us;
let f = move |&mut:| drop(x); //~ cannot move
let f = move |&mut:| drop(x); //~ ERROR cannot move
}
{
let x = box 0us;

View file

@ -0,0 +1,24 @@
// Copyright 2015 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.
// Test that a by-ref `FnMut` closure gets an error when it tries to
// consume a value.
fn call<F>(f: F) where F : Fn() {
f();
}
fn main() {
let y = vec!(format!("World"));
call(|| {
y.into_iter();
//~^ ERROR cannot move out of captured outer variable in an `Fn` closure
});
}

View file

@ -0,0 +1,62 @@
// Copyright 2015 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.
// Test that we cannot mutate an outer variable that is not declared
// as `mut` through a closure. Also test that we CAN mutate a moved copy,
// unless this is a `Fn` closure. Issue #16749.
use std::mem;
fn a() {
let n = 0u8;
let mut f = |&mut:| { //~ ERROR closure cannot assign
n += 1;
};
}
fn b() {
let mut n = 0u8;
let mut f = |&mut:| {
n += 1; // OK
};
}
fn c() {
let n = 0u8;
let mut f = move |&mut:| {
// If we just did a straight-forward desugaring, this would
// compile, but we do something a bit more subtle, and hence
// we get an error.
n += 1; //~ ERROR cannot assign
};
}
fn d() {
let mut n = 0u8;
let mut f = move |&mut:| {
n += 1; // OK
};
}
fn e() {
let n = 0u8;
let mut f = move |&:| {
n += 1; //~ ERROR cannot assign
};
}
fn f() {
let mut n = 0u8;
let mut f = move |&:| {
n += 1; //~ ERROR cannot assign
};
}
fn main() { }

View file

@ -0,0 +1,24 @@
// Copyright 2015 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.
// Test that a by-ref `FnMut` closure gets an error when it tries to
// mutate a value.
fn call<F>(f: F) where F : Fn() {
f();
}
fn main() {
let mut counter = 0_u32;
call(|| {
counter += 1;
//~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
});
}

View file

@ -0,0 +1,36 @@
// Copyright 2015 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.
// Test that we mutate a counter on the stack only when we expect to.
fn call<F>(f: F) where F : FnOnce() {
f();
}
fn main() {
let y = vec!(format!("Hello"), format!("World"));
let mut counter = 22_u32;
call(|| {
// Move `y`, but do not move `counter`, even though it is read
// by value (note that it is also mutated).
for item in y.into_iter() {
let v = counter;
counter += v;
}
});
assert_eq!(counter, 88);
call(move || {
// this mutates a moved copy, and hence doesn't affect original
counter += 1;
});
assert_eq!(counter, 88);
}

View file

@ -0,0 +1,32 @@
// Copyright 2015 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.
// Test that in a by-ref once closure we move some variables even as
// we capture others by mutable reference.
fn call<F>(f: F) where F : FnOnce() {
f();
}
fn main() {
let mut x = vec!(format!("Hello"));
let y = vec!(format!("World"));
call(|| {
// Here: `x` must be captured with a mutable reference in
// order for us to append on it, and `y` must be captured by
// value.
for item in y.into_iter() {
x.push(item);
}
});
assert_eq!(x.len(), 2);
assert_eq!(&*x[0], "Hello");
assert_eq!(&*x[1], "World");
}