diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2014-07-25 15:18:19 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2014-07-25 15:26:21 -0700 |
| commit | b2eb88843d1b727551464beea3438e9f0159ebad (patch) | |
| tree | 2cf168c0a767d763ef5a22758314688678e6e515 /src/test | |
| parent | 66a0b528a6601d060095655f31c7d38e2a841511 (diff) | |
| download | rust-b2eb88843d1b727551464beea3438e9f0159ebad.tar.gz rust-b2eb88843d1b727551464beea3438e9f0159ebad.zip | |
librustc: Disallow mutation and assignment in pattern guards, and modify
the CFG for match statements.
There were two bugs in issue #14684. One was simply that the borrow
check didn't know about the correct CFG for match statements: the
pattern must be a predecessor of the guard. This disallows the bad
behavior if there are bindings in the pattern. But it isn't enough to
prevent the memory safety problem, because of wildcards; thus, this
patch introduces a more restrictive rule, which disallows assignments
and mutable borrows inside guards outright.
I discussed this with Niko and we decided this was the best plan of
action.
This breaks code that performs mutable borrows in pattern guards. Most
commonly, the code looks like this:
impl Foo {
fn f(&mut self, ...) {}
fn g(&mut self, ...) {
match bar {
Baz if self.f(...) => { ... }
_ => { ... }
}
}
}
Change this code to not use a guard. For example:
impl Foo {
fn f(&mut self, ...) {}
fn g(&mut self, ...) {
match bar {
Baz => {
if self.f(...) {
...
} else {
...
}
}
_ => { ... }
}
}
}
Sometimes this can result in code duplication, but often it illustrates
a hidden memory safety problem.
Closes #14684.
[breaking-change]
Diffstat (limited to 'src/test')
4 files changed, 68 insertions, 56 deletions
diff --git a/src/test/compile-fail/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck-lend-flow-match.rs index c6020df2bc2..049bec3d37b 100644 --- a/src/test/compile-fail/borrowck-lend-flow-match.rs +++ b/src/test/compile-fail/borrowck-lend-flow-match.rs @@ -11,9 +11,6 @@ #![allow(unused_variable)] #![allow(dead_assignment)] -fn cond() -> bool { fail!() } -fn link<'a>(v: &'a uint, w: &mut &'a uint) -> bool { *w = v; true } - fn separate_arms() { // Here both arms perform assignments, but only is illegal. @@ -31,28 +28,4 @@ fn separate_arms() { x.clone(); // just to prevent liveness warnings } -fn guard() { - // Here the guard performs a borrow. This borrow "infects" all - // subsequent arms (but not the prior ones). - - let mut a = box 3u; - let mut b = box 4u; - let mut w = &*a; - match 22i { - _ if cond() => { - b = box 5u; - } - - _ if link(&*b, &mut w) => { - b = box 6u; //~ ERROR cannot assign - } - - _ => { - b = box 7u; //~ ERROR cannot assign - } - } - - b = box 8; //~ ERROR cannot assign -} - fn main() {} diff --git a/src/test/compile-fail/borrowck-mutate-in-guard.rs b/src/test/compile-fail/borrowck-mutate-in-guard.rs new file mode 100644 index 00000000000..8a904a3b5fb --- /dev/null +++ b/src/test/compile-fail/borrowck-mutate-in-guard.rs @@ -0,0 +1,33 @@ +// 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. + +enum Enum<'a> { + A(&'a int), + B(bool), +} + +fn foo() -> int { + let mut n = 42; + let mut x = A(&mut n); + match x { + A(_) if { x = B(false); false } => 1, + //~^ ERROR cannot assign in a pattern guard + A(_) if { let y = &mut x; *y = B(false); false } => 1, + //~^ ERROR cannot mutably borrow in a pattern guard + //~^^ ERROR cannot assign in a pattern guard + A(p) => *p, + B(_) => 2, + } +} + +fn main() { + foo(); +} + diff --git a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot index 251798fc7ed..f0907d8d708 100644 --- a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot @@ -7,14 +7,15 @@ digraph block { N5[label="expr 7777i"]; N6[label="expr [7i, 77i, 777i, 7777i]"]; N7[label="expr match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y }"]; - N8[label="local x"]; - N9[label="local y"]; - N10[label="pat .."]; - N11[label="pat [x, y, ..]"]; - N12[label="expr x"]; - N13[label="expr y"]; - N14[label="expr x + y"]; - N15[label="block { match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y }; }"]; + N8[label="(dummy_node)"]; + N9[label="local x"]; + N10[label="local y"]; + N11[label="pat .."]; + N12[label="pat [x, y, ..]"]; + N13[label="expr x"]; + N14[label="expr y"]; + N15[label="expr x + y"]; + N16[label="block { match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y }; }"]; N0 -> N2; N2 -> N3; N3 -> N4; @@ -27,7 +28,8 @@ digraph block { N11 -> N12; N12 -> N13; N13 -> N14; - N14 -> N7; - N7 -> N15; - N15 -> N1; + N14 -> N15; + N15 -> N7; + N7 -> N16; + N16 -> N1; } diff --git a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot index 2be43dcaa7b..dbfa4dd6fe9 100644 --- a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot @@ -8,18 +8,20 @@ digraph block { N6[label="local _y"]; N7[label="expr x"]; N8[label="expr match x { E13a => _y = 1, E13b(v) => _y = v + 1 }"]; - N9[label="local E13a"]; - N10[label="expr 1"]; - N11[label="expr _y"]; - N12[label="expr _y = 1"]; - N13[label="local v"]; - N14[label="pat E13b(v)"]; - N15[label="expr v"]; - N16[label="expr 1"]; - N17[label="expr v + 1"]; - N18[label="expr _y"]; - N19[label="expr _y = v + 1"]; - N20[label="block {\l let x = E13b(13);\l let _y;\l match x { E13a => _y = 1, E13b(v) => _y = v + 1 }\l}\l"]; + N9[label="(dummy_node)"]; + N10[label="local E13a"]; + N11[label="expr 1"]; + N12[label="expr _y"]; + N13[label="expr _y = 1"]; + N14[label="(dummy_node)"]; + N15[label="local v"]; + N16[label="pat E13b(v)"]; + N17[label="expr v"]; + N18[label="expr 1"]; + N19[label="expr v + 1"]; + N20[label="expr _y"]; + N21[label="expr _y = v + 1"]; + N22[label="block {\l let x = E13b(13);\l let _y;\l match x { E13a => _y = 1, E13b(v) => _y = v + 1 }\l}\l"]; N0 -> N2; N2 -> N3; N3 -> N4; @@ -30,15 +32,17 @@ digraph block { N9 -> N10; N10 -> N11; N11 -> N12; - N12 -> N8; - N7 -> N13; - N13 -> N14; + N12 -> N13; + N13 -> N8; + N9 -> N14; N14 -> N15; N15 -> N16; N16 -> N17; N17 -> N18; N18 -> N19; - N19 -> N8; - N8 -> N20; - N20 -> N1; + N19 -> N20; + N20 -> N21; + N21 -> N8; + N8 -> N22; + N22 -> N1; } |
