diff options
| author | bors <bors@rust-lang.org> | 2014-10-17 02:07:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-10-17 02:07:24 +0000 |
| commit | 3dec727297e6ebd6614219a93f376d8181ab11b1 (patch) | |
| tree | 3b32606a720eb3baa059837b0f0c4068cc8f54ee /src/test | |
| parent | 1600e0b93c4edf10bce71fbb68d383827c40a153 (diff) | |
| parent | fdd69accd0c9366b882a0e0d93ddb94eee307431 (diff) | |
auto merge of #17869 : bkoropoff/rust/bound-all-the-upvars, r=nikomatsakis
This PR is based on #17784, which fixes closure soundness problems in borrowck. Only the last two commits are unique to this PR. My understanding of regionck is still evolving, so I'm not sure if this is the right approach. Feedback is appreciated. - In `link_reborrowed_region`, we account for the ability of upvars to change their mutability due to later processing. A map of recursive region links we may want to establish in the future is maintained, with the links being established when the mutability of the borrow is adjusted. - When asked to establish a region link for an upvar, we link it to the region of the closure body. This creates the necessary constraint to stop unsound reborrows from the closure environment. This partially (maybe completely) solves issue #17403. Remaining work: - This is only known to help with by-ref upvars. I have not looked at by-value upvars yet to see if they can cause problems. - The error diagnostics that result from failed region inference are pretty inscrutible.
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/compile-fail/borrow-immutable-upvar-mutation.rs (renamed from src/test/compile-fail/issue-17780.rs) | 27 | ||||
| -rw-r--r-- | src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs | 30 | ||||
| -rw-r--r-- | src/test/compile-fail/unboxed-closure-illegal-move.rs | 44 |
3 files changed, 83 insertions, 18 deletions
diff --git a/src/test/compile-fail/issue-17780.rs b/src/test/compile-fail/borrow-immutable-upvar-mutation.rs index 2072b2ee2d2..f748c400654 100644 --- a/src/test/compile-fail/issue-17780.rs +++ b/src/test/compile-fail/borrow-immutable-upvar-mutation.rs @@ -10,41 +10,32 @@ #![feature(unboxed_closures, overloaded_calls)] +// Tests that we can't assign to or mutably borrow upvars from `Fn` +// closures (issue #17780) + fn set(x: &mut uint) { *x = 5; } fn main() { // By-ref captures { let mut x = 0u; - let _f = |&:| x = 42; - //~^ ERROR cannot assign to data in a free - // variable from an immutable unboxed closure + let _f = |&:| x = 42; //~ ERROR cannot assign let mut y = 0u; - let _g = |&:| set(&mut y); - //~^ ERROR cannot borrow data mutably in a free - // variable from an immutable unboxed closure + let _g = |&:| set(&mut y); //~ ERROR cannot borrow let mut z = 0u; - let _h = |&mut:| { set(&mut z); |&:| z = 42; }; - //~^ ERROR cannot assign to data in a - // free variable from an immutable unboxed closure + let _h = |&mut:| { set(&mut z); |&:| z = 42; }; //~ ERROR cannot assign } // By-value captures { let mut x = 0u; - let _f = move |&:| x = 42; - //~^ ERROR cannot assign to data in a free - // variable from an immutable unboxed closure + let _f = move |&:| x = 42; //~ ERROR cannot assign let mut y = 0u; - let _g = move |&:| set(&mut y); - //~^ ERROR cannot borrow data mutably in a free - // variable from an immutable unboxed closure + let _g = move |&:| set(&mut y); //~ ERROR cannot borrow let mut z = 0u; - let _h = move |&mut:| { set(&mut z); move |&:| z = 42; }; - //~^ ERROR cannot assign to data in a free - // variable from an immutable unboxed closure + let _h = move |&mut:| { set(&mut z); move |&:| z = 42; }; //~ ERROR cannot assign } } diff --git a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs new file mode 100644 index 00000000000..aedaced5794 --- /dev/null +++ b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs @@ -0,0 +1,30 @@ +// 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. + +// Test that closures cannot subvert aliasing restrictions + +#![feature(overloaded_calls, unboxed_closures)] + +fn main() { + // Unboxed closure case + { + let mut x = 0u; + let mut f = |&mut:| &mut x; //~ ERROR cannot infer + let x = f(); + let y = f(); + } + // Boxed closure case + { + let mut x = 0u; + let f = || &mut x; //~ ERROR cannot infer + let x = f(); + let y = f(); + } +} diff --git a/src/test/compile-fail/unboxed-closure-illegal-move.rs b/src/test/compile-fail/unboxed-closure-illegal-move.rs new file mode 100644 index 00000000000..9e981f2c9bb --- /dev/null +++ b/src/test/compile-fail/unboxed-closure-illegal-move.rs @@ -0,0 +1,44 @@ +// 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_closures)] + +// Tests that we can't move out of an unboxed closure environment +// if the upvar is captured by ref or the closure takes self by +// reference. + +fn main() { + // By-ref cases + { + let x = box 0u; + let f = |&:| drop(x); //~ cannot move + } + { + let x = box 0u; + let f = |&mut:| drop(x); //~ cannot move + } + { + let x = box 0u; + let f = |:| drop(x); //~ cannot move + } + // By-value cases + { + let x = box 0u; + let f = move |&:| drop(x); //~ cannot move + } + { + let x = box 0u; + let f = move |&mut:| drop(x); //~ cannot move + } + { + let x = box 0u; + let f = move |:| drop(x); // this one is ok + } +} |
