Skip to content

Commit 98d5e13

Browse files
committed
Tests illustrating the bug fixes for #27282 and #24535.
1 parent 5eebd36 commit 98d5e13

7 files changed

+211
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This test illustrates that under NLL, we can remove our overly
12+
// conservative approach for disallowing mutations of match inputs.
13+
14+
// See further discussion on rust-lang/rust#24535 and
15+
// rust-lang/rfcs#1006.
16+
17+
// compile-flags: -Z disable-ast-check-for-mutation-in-guard
18+
19+
#![feature(nll)]
20+
21+
fn main() {
22+
rust_issue_24535();
23+
rfcs_issue_1006_1();
24+
rfcs_issue_1006_2();
25+
}
26+
27+
fn rust_issue_24535() {
28+
fn compare(a: &u8, b: &mut u8) -> bool {
29+
a == b
30+
}
31+
32+
let a = 3u8;
33+
34+
match a {
35+
0 => panic!("nope"),
36+
3 if compare(&a, &mut 3) => (),
37+
_ => panic!("nope"),
38+
}
39+
}
40+
41+
fn rfcs_issue_1006_1() {
42+
let v = vec!["1".to_string(), "2".to_string(), "3".to_string()];
43+
match Some(&v) {
44+
Some(iv) if iv.iter().any(|x| &x[..]=="2") => true,
45+
_ => panic!("nope"),
46+
};
47+
}
48+
49+
fn rfcs_issue_1006_2() {
50+
#[inline(always)]
51+
fn check<'a, I: Iterator<Item=&'a i32>>(mut i: I) -> bool {
52+
i.any(|&x| x == 2)
53+
}
54+
55+
let slice = [1, 2, 3];
56+
57+
match 42 {
58+
_ if slice.iter().any(|&x| x == 2) => { true },
59+
_ => { panic!("nope"); }
60+
};
61+
62+
// (This match is just illustrating how easy it was to circumvent
63+
// the checking performed for the previous `match`.)
64+
match 42 {
65+
_ if check(slice.iter()) => { true },
66+
_ => { panic!("nope"); }
67+
};
68+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Issue 27282: Example 2: This sidesteps the AST checks disallowing
12+
// mutable borrows in match guards by hiding the mutable borrow in a
13+
// guard behind a move (of the mutably borrowed match input) within a
14+
// closure.
15+
//
16+
// This example is not rejected by AST borrowck (and then reliably
17+
// reaches the panic code when executed, despite the compiler warning
18+
// about that match arm being unreachable.
19+
20+
#![feature(nll)]
21+
22+
fn main() {
23+
let b = &mut true;
24+
match b {
25+
&mut false => {},
26+
_ if { (|| { let bar = b; *bar = false; })();
27+
//~^ ERROR cannot move out of `b` because it is borrowed [E0505]
28+
false } => { },
29+
&mut true => { println!("You might think we should get here"); },
30+
//~^ ERROR use of moved value: `*b` [E0382]
31+
_ => panic!("surely we could never get here, since rustc warns it is unreachable."),
32+
}
33+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0505]: cannot move out of `b` because it is borrowed
2+
--> $DIR/issue-27282-move-match-input-into-guard.rs:26:16
3+
|
4+
LL | match b {
5+
| _____-
6+
| |_____|
7+
| ||
8+
LL | || &mut false => {},
9+
LL | || _ if { (|| { let bar = b; *bar = false; })();
10+
| || ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here
11+
LL | || //~^ ERROR cannot move out of `b` because it is borrowed [E0505]
12+
... ||
13+
LL | || _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
14+
LL | || }
15+
| || -
16+
| ||_____|
17+
| |______borrow of `b` occurs here
18+
| borrow later used here
19+
20+
error[E0382]: use of moved value: `*b`
21+
--> $DIR/issue-27282-move-match-input-into-guard.rs:29:14
22+
|
23+
LL | _ if { (|| { let bar = b; *bar = false; })();
24+
| ----------------------------------- value moved here
25+
...
26+
LL | &mut true => { println!("You might think we should get here"); },
27+
| ^^^^ value used here after move
28+
29+
error: aborting due to 2 previous errors
30+
31+
Some errors occurred: E0382, E0505.
32+
For more information about an error, try `rustc --explain E0382`.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Issue 27282: Example 1: This sidesteps the AST checks disallowing
12+
// mutable borrows in match guards by hiding the mutable borrow in a
13+
// guard behind a move (of the ref mut pattern id) within a closure.
14+
//
15+
// This example is not rejected by AST borrowck (and then reliably
16+
// segfaults when executed).
17+
18+
#![feature(nll)]
19+
20+
fn main() {
21+
match Some(&4) {
22+
None => {},
23+
ref mut foo
24+
if { (|| { let bar = foo; bar.take() })(); false } => {},
25+
//~^ ERROR cannot move out of borrowed content [E0507]
26+
Some(s) => std::process::exit(*s),
27+
}
28+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0507]: cannot move out of borrowed content
2+
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:24:18
3+
|
4+
LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0507`.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Issue 27282: This is a variation on issue-27282-move-ref-mut-into-guard.rs
12+
//
13+
// It reborrows instead of moving the `ref mut` pattern borrow. This
14+
// means that our conservative check for mutation in guards will
15+
// reject it. But I want to make sure that we continue to reject it
16+
// (under NLL) even when that conservaive check goes away.
17+
18+
// compile-flags: -Z disable-ast-check-for-mutation-in-guard
19+
20+
#![feature(nll)]
21+
22+
fn main() {
23+
let mut b = &mut true;
24+
match b {
25+
&mut false => {},
26+
ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
27+
//~^ ERROR cannot borrow immutable item `*r` as mutable
28+
false } => { &mut *r; },
29+
&mut true => { println!("You might think we should get here"); },
30+
_ => panic!("surely we could never get here, since rustc warns it is unreachable."),
31+
}
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0596]: cannot borrow immutable item `*r` as mutable
2+
--> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:26:24
3+
|
4+
LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0596`.

0 commit comments

Comments
 (0)