diff options
| author | bors <bors@rust-lang.org> | 2014-08-14 16:36:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-08-14 16:36:19 +0000 |
| commit | 404978ea722c0257cc763540c93243e8a21f82ed (patch) | |
| tree | c6106879c326924dc3d39ce71c0a797901bafe04 /src/test | |
| parent | 56b86aaf35d96ec8cf8555205426eaed62427963 (diff) | |
| parent | 8d272321417df3a954802e42a66adda87ade5a49 (diff) | |
| download | rust-404978ea722c0257cc763540c93243e8a21f82ed.tar.gz rust-404978ea722c0257cc763540c93243e8a21f82ed.zip | |
auto merge of #16122 : pcwalton/rust/lifetimes-in-unboxed-closures, r=pnkfelix
This patch primarily does two things: (1) it prevents lifetimes from
leaking out of unboxed closures; (2) it allows unboxed closure type
notation, call notation, and construction notation to construct closures
matching any of the three traits.
This breaks code that looked like:
let mut f;
{
let x = &5i;
f = |&mut:| *x + 10;
}
Change this code to avoid having a reference escape. For example:
{
let x = &5i;
let mut f; // <-- move here to avoid dangling reference
f = |&mut:| *x + 10;
}
I believe this is enough to consider unboxed closures essentially
implemented. Further issues (for example, higher-rank lifetimes) should
be filed as followups.
Closes #14449.
[breaking-change]
r? @pnkfelix
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/compile-fail/borrowck-unboxed-closures.rs | 29 | ||||
| -rw-r--r-- | src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs | 24 | ||||
| -rw-r--r-- | src/test/compile-fail/unboxed-closures-wrong-trait.rs | 22 | ||||
| -rw-r--r-- | src/test/run-pass/unboxed-closures-all-traits.rs | 31 | ||||
| -rw-r--r-- | src/test/run-pass/unboxed-closures-drop.rs | 127 | ||||
| -rw-r--r-- | src/test/run-pass/unboxed-closures-single-word-env.rs | 34 |
6 files changed, 267 insertions, 0 deletions
diff --git a/src/test/compile-fail/borrowck-unboxed-closures.rs b/src/test/compile-fail/borrowck-unboxed-closures.rs new file mode 100644 index 00000000000..d822bb22e2a --- /dev/null +++ b/src/test/compile-fail/borrowck-unboxed-closures.rs @@ -0,0 +1,29 @@ +// 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. + +#![feature(overloaded_calls)] + +fn a<F:|&: int, int| -> int>(mut f: F) { + let g = &mut f; + f(1, 2); //~ ERROR cannot borrow `f` as immutable + //~^ ERROR cannot borrow `f` as immutable +} + +fn b<F:|&mut: int, int| -> int>(f: F) { + f(1, 2); //~ ERROR cannot borrow immutable argument +} + +fn c<F:|: int, int| -> int>(f: F) { + f(1, 2); + f(1, 2); //~ ERROR use of moved value +} + +fn main() {} + diff --git a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs new file mode 100644 index 00000000000..1c590db11e3 --- /dev/null +++ b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs @@ -0,0 +1,24 @@ +// 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. + +#![feature(unboxed_closure_sugar, unboxed_closures, overloaded_calls)] + +use std::ops::FnMut; + +fn main() { + let mut f; + { + let c = 1; + let c_ref = &c; + f = |&mut: a: int, b: int| { a + b + *c_ref }; + //~^ ERROR cannot infer an appropriate lifetime + } +} + diff --git a/src/test/compile-fail/unboxed-closures-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-wrong-trait.rs new file mode 100644 index 00000000000..50d90c6200e --- /dev/null +++ b/src/test/compile-fail/unboxed-closures-wrong-trait.rs @@ -0,0 +1,22 @@ +// 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. + +#![feature(lang_items, overloaded_calls, unboxed_closures)] + +fn c<F:|: int, int| -> int>(f: F) -> int { + f(5, 6) +} + +fn main() { + let z: int = 7; + assert_eq!(c(|&: x: int, y| x + y + z), 10); + //~^ ERROR failed to find an implementation +} + diff --git a/src/test/run-pass/unboxed-closures-all-traits.rs b/src/test/run-pass/unboxed-closures-all-traits.rs new file mode 100644 index 00000000000..c362a83e60c --- /dev/null +++ b/src/test/run-pass/unboxed-closures-all-traits.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. + +#![feature(lang_items, overloaded_calls, unboxed_closures)] + +fn a<F:|&: int, int| -> int>(f: F) -> int { + f(1, 2) +} + +fn b<F:|&mut: int, int| -> int>(mut f: F) -> int { + f(3, 4) +} + +fn c<F:|: int, int| -> int>(f: F) -> int { + f(5, 6) +} + +fn main() { + let z: int = 7; + assert_eq!(a(|&: x: int, y| x + y + z), 10); + assert_eq!(b(|&mut: x: int, y| x + y + z), 14); + assert_eq!(c(|: x: int, y| x + y + z), 18); +} + diff --git a/src/test/run-pass/unboxed-closures-drop.rs b/src/test/run-pass/unboxed-closures-drop.rs new file mode 100644 index 00000000000..f20dddcae54 --- /dev/null +++ b/src/test/run-pass/unboxed-closures-drop.rs @@ -0,0 +1,127 @@ +// 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. + +// A battery of tests to ensure destructors of unboxed closure environments +// run at the right times. + +#![feature(overloaded_calls, unboxed_closures)] + +static mut DROP_COUNT: uint = 0; + +fn drop_count() -> uint { + unsafe { + DROP_COUNT + } +} + +struct Droppable { + x: int, +} + +impl Droppable { + fn new() -> Droppable { + Droppable { + x: 1 + } + } +} + +impl Drop for Droppable { + fn drop(&mut self) { + unsafe { + DROP_COUNT += 1 + } + } +} + +fn a<F:|&: int, int| -> int>(f: F) -> int { + f(1, 2) +} + +fn b<F:|&mut: int, int| -> int>(mut f: F) -> int { + f(3, 4) +} + +fn c<F:|: int, int| -> int>(f: F) -> int { + f(5, 6) +} + +fn test_fn() { + { + a(|&: a: int, b| { a + b }); + } + assert_eq!(drop_count(), 0); + + { + let z = &Droppable::new(); + a(|&: a: int, b| { z; a + b }); + assert_eq!(drop_count(), 0); + } + assert_eq!(drop_count(), 1); + + { + let z = &Droppable::new(); + let zz = &Droppable::new(); + a(|&: a: int, b| { z; zz; a + b }); + assert_eq!(drop_count(), 1); + } + assert_eq!(drop_count(), 3); +} + +fn test_fn_mut() { + { + b(|&mut: a: int, b| { a + b }); + } + assert_eq!(drop_count(), 3); + + { + let z = &Droppable::new(); + b(|&mut: a: int, b| { z; a + b }); + assert_eq!(drop_count(), 3); + } + assert_eq!(drop_count(), 4); + + { + let z = &Droppable::new(); + let zz = &Droppable::new(); + b(|&mut: a: int, b| { z; zz; a + b }); + assert_eq!(drop_count(), 4); + } + assert_eq!(drop_count(), 6); +} + +fn test_fn_once() { + { + c(|: a: int, b| { a + b }); + } + assert_eq!(drop_count(), 6); + + { + let z = Droppable::new(); + c(|: a: int, b| { z; a + b }); + assert_eq!(drop_count(), 7); + } + assert_eq!(drop_count(), 7); + + { + let z = Droppable::new(); + let zz = Droppable::new(); + c(|: a: int, b| { z; zz; a + b }); + assert_eq!(drop_count(), 9); + } + assert_eq!(drop_count(), 9); +} + +fn main() { + test_fn(); + test_fn_mut(); + test_fn_once(); +} + diff --git a/src/test/run-pass/unboxed-closures-single-word-env.rs b/src/test/run-pass/unboxed-closures-single-word-env.rs new file mode 100644 index 00000000000..754b1f70644 --- /dev/null +++ b/src/test/run-pass/unboxed-closures-single-word-env.rs @@ -0,0 +1,34 @@ +// 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. + +// Ensures that single-word environments work right in unboxed closures. +// These take a different path in codegen. + +#![feature(overloaded_calls, unboxed_closures)] + +fn a<F:|&: int, int| -> int>(f: F) -> int { + f(1, 2) +} + +fn b<F:|&mut: int, int| -> int>(mut f: F) -> int { + f(3, 4) +} + +fn c<F:|: int, int| -> int>(f: F) -> int { + f(5, 6) +} + +fn main() { + let z = 10; + assert_eq!(a(|&: x: int, y| x + y + z), 13); + assert_eq!(b(|&mut: x: int, y| x + y + z), 17); + assert_eq!(c(|: x: int, y| x + y + z), 21); +} + |
