From c9e3cb678d556926c491d977550fbd805892d4af Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 10 Feb 2014 07:44:21 -0500 Subject: [PATCH] test -- add new tests specifically examining closure borrows --- .../borrowck-closures-mut-and-imm.rs | 79 +++++++++++++++++++ .../borrowck-closures-mut-of-imm.rs | 31 ++++++++ .../compile-fail/borrowck-closures-two-mut.rs | 56 +++++++++++++ .../compile-fail/borrowck-closures-unique.rs | 50 ++++++++++++ .../borrowck-closures-use-after-free.rs | 31 ++++++++ .../run-pass/borrowck-closures-two-imm.rs | 49 ++++++++++++ 6 files changed, 296 insertions(+) create mode 100644 src/test/compile-fail/borrowck-closures-mut-and-imm.rs create mode 100644 src/test/compile-fail/borrowck-closures-mut-of-imm.rs create mode 100644 src/test/compile-fail/borrowck-closures-two-mut.rs create mode 100644 src/test/compile-fail/borrowck-closures-unique.rs create mode 100644 src/test/compile-fail/borrowck-closures-use-after-free.rs create mode 100644 src/test/run-pass/borrowck-closures-two-imm.rs diff --git a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck-closures-mut-and-imm.rs new file mode 100644 index 0000000000000..006f475b29d4e --- /dev/null +++ b/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 or the MIT license +// , 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() { +} diff --git a/src/test/compile-fail/borrowck-closures-mut-of-imm.rs b/src/test/compile-fail/borrowck-closures-mut-of-imm.rs new file mode 100644 index 0000000000000..cdfb569762de3 --- /dev/null +++ b/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 or the MIT license +// , 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() { +} diff --git a/src/test/compile-fail/borrowck-closures-two-mut.rs b/src/test/compile-fail/borrowck-closures-two-mut.rs new file mode 100644 index 0000000000000..570249aed443b --- /dev/null +++ b/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 or the MIT license +// , 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() { +} diff --git a/src/test/compile-fail/borrowck-closures-unique.rs b/src/test/compile-fail/borrowck-closures-unique.rs new file mode 100644 index 0000000000000..80d942e58d15c --- /dev/null +++ b/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 or the MIT license +// , 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() { +} diff --git a/src/test/compile-fail/borrowck-closures-use-after-free.rs b/src/test/compile-fail/borrowck-closures-use-after-free.rs new file mode 100644 index 0000000000000..38c13b1fce94f --- /dev/null +++ b/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 or the MIT license +// , 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` +} diff --git a/src/test/run-pass/borrowck-closures-two-imm.rs b/src/test/run-pass/borrowck-closures-two-imm.rs new file mode 100644 index 0000000000000..3bd12b030411e --- /dev/null +++ b/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 or the MIT license +// , 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); +}