Skip to content

Commit

Permalink
test -- add new tests specifically examining closure borrows
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Feb 11, 2014
1 parent 3805c54 commit c9e3cb6
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 0 deletions.
79 changes: 79 additions & 0 deletions src/test/compile-fail/borrowck-closures-mut-and-imm.rs
@@ -0,0 +1,79 @@
// 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.

// Tests that two closures cannot simultaneously have mutable
// and immutable access to the variable. Issue #6801.

fn get(x: &int) -> int {
*x
}

fn set(x: &mut int) {
*x = 4;
}

fn a() {
let mut x = 3;
let c1 = || x = 4;
let c2 = || x * 5; //~ ERROR cannot borrow `x`
}

fn b() {
let mut x = 3;
let c1 = || set(&mut x);
let c2 = || get(&x); //~ ERROR cannot borrow `x`
}

fn c() {
let mut x = 3;
let c1 = || set(&mut x);
let c2 = || x * 5; //~ ERROR cannot borrow `x`
}

fn d() {
let mut x = 3;
let c2 = || x * 5;
x = 5; //~ ERROR cannot assign
}

fn e() {
let mut x = 3;
let c1 = || get(&x);
x = 5; //~ ERROR cannot assign
}

fn f() {
let mut x = ~3;
let c1 = || get(&*x);
*x = 5; //~ ERROR cannot assign
}

fn g() {
struct Foo {
f: ~int
}

let mut x = ~Foo { f: ~3 };
let c1 = || get(&*x.f);
*x.f = 5; //~ ERROR cannot assign to `*x.f`
}

fn h() {
struct Foo {
f: ~int
}

let mut x = ~Foo { f: ~3 };
let c1 = || get(&*x.f);
let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable
}

fn main() {
}
31 changes: 31 additions & 0 deletions src/test/compile-fail/borrowck-closures-mut-of-imm.rs
@@ -0,0 +1,31 @@
// 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.

// Tests that two closures cannot simultaneously have mutable
// and immutable access to the variable. Issue #6801.

fn get(x: &int) -> int {
*x
}

fn set(x: &mut int) {
*x = 4;
}

fn a(x: &int) {
let c1 = || set(&mut *x);
//~^ ERROR cannot borrow
let c2 = || set(&mut *x);
//~^ ERROR closure requires unique access to `x`
//~^^ ERROR cannot borrow
}

fn main() {
}
56 changes: 56 additions & 0 deletions src/test/compile-fail/borrowck-closures-two-mut.rs
@@ -0,0 +1,56 @@
// 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.

// Tests that two closures cannot simultaneously have mutable
// access to the variable, whether that mutable access be used
// for direct assignment or for taking mutable ref. Issue #6801.

fn a() {
let mut x = 3;
let c1 = || x = 4;
let c2 = || x = 5; //~ ERROR cannot borrow `x` as mutable more than once
}

fn set(x: &mut int) {
*x = 4;
}

fn b() {
let mut x = 3;
let c1 = || set(&mut x);
let c2 = || set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once
}

fn c() {
let mut x = 3;
let c1 = || x = 5;
let c2 = || set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once
}

fn d() {
let mut x = 3;
let c1 = || x = 5;
let c2 = || { let _y = || set(&mut x); }; // (nested closure)
//~^ ERROR cannot borrow `x` as mutable more than once
}

fn g() {
struct Foo {
f: ~int
}

let mut x = ~Foo { f: ~3 };
let c1 = || set(&mut *x.f);
let c2 = || set(&mut *x.f);
//~^ ERROR cannot borrow `x` as mutable more than once
}

fn main() {
}
50 changes: 50 additions & 0 deletions src/test/compile-fail/borrowck-closures-unique.rs
@@ -0,0 +1,50 @@
// 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.

// Tests that a closure which requires mutable access to the referent
// of an `&mut` requires a "unique" borrow -- that is, the variable to
// be borrowed (here, `x`) will not be borrowed *mutably*, but
// may be *immutable*, but we cannot allow
// multiple borrows.

fn get(x: &int) -> int {
*x
}

fn set(x: &mut int) -> int {
*x
}

fn a(x: &mut int) {
let c1 = || get(x);
let c2 = || get(x);
}

fn b(x: &mut int) {
let c1 = || get(x);
let c2 = || set(x); //~ ERROR closure requires unique access to `x`
}

fn c(x: &mut int) {
let c1 = || get(x);
let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
}

fn d(x: &mut int) {
let c1 = || set(x);
let c2 = || set(x); //~ ERROR closure requires unique access to `x`
}

fn e(x: &mut int) {
let c1: || = || x = fail!(); //~ ERROR closure cannot assign to immutable argument `x`
}

fn main() {
}
31 changes: 31 additions & 0 deletions src/test/compile-fail/borrowck-closures-use-after-free.rs
@@ -0,0 +1,31 @@
// 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.

// Tests that a closure which mutates a local variable
// cannot also be supplied a borrowed version of that
// variable's contents. Issue #11192.

struct Foo {
x: int
}

impl Drop for Foo {
fn drop(&mut self) {
println!("drop {}", self.x);
}
}

fn main() {
let mut ptr = ~Foo { x: 0 };
let test = |foo: &Foo| {
ptr = ~Foo { x: ptr.x + 1 };
};
test(ptr); //~ ERROR cannot borrow `*ptr`
}
49 changes: 49 additions & 0 deletions src/test/run-pass/borrowck-closures-two-imm.rs
@@ -0,0 +1,49 @@
// 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.

// Tests that two closures can simultaneously have immutable
// access to the variable, whether that immutable access be used
// for direct reads or for taking immutable ref. Also check
// that the main function can read the variable too while
// the closures are in scope. Issue #6801.

fn a() -> int {
let mut x = 3;
x += 1;
let c1 = || x * 4;
let c2 = || x * 5;
c1() * c2() * x
}

fn get(x: &int) -> int {
*x * 4
}

fn b() -> int {
let mut x = 3;
x += 1;
let c1 = || get(&x);
let c2 = || get(&x);
c1() * c2() * x
}

fn c() -> int {
let mut x = 3;
x += 1;
let c1 = || x * 5;
let c2 = || get(&x);
c1() * c2() * x
}

pub fn main() {
assert_eq!(a(), 1280);
assert_eq!(b(), 1024);
assert_eq!(c(), 1280);
}

0 comments on commit c9e3cb6

Please sign in to comment.