Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
7 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
src/test/run-pass/issue-24535-allow-mutable-borrow-in-match-guard.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright 2018 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. | ||
|
||
// This test illustrates that under NLL, we can remove our overly | ||
// conservative approach for disallowing mutations of match inputs. | ||
|
||
// See further discussion on rust-lang/rust#24535 and | ||
// rust-lang/rfcs#1006. | ||
|
||
// compile-flags: -Z disable-ast-check-for-mutation-in-guard | ||
|
||
#![feature(nll)] | ||
|
||
fn main() { | ||
rust_issue_24535(); | ||
rfcs_issue_1006_1(); | ||
rfcs_issue_1006_2(); | ||
} | ||
|
||
fn rust_issue_24535() { | ||
fn compare(a: &u8, b: &mut u8) -> bool { | ||
a == b | ||
} | ||
|
||
let a = 3u8; | ||
|
||
match a { | ||
0 => panic!("nope"), | ||
3 if compare(&a, &mut 3) => (), | ||
_ => panic!("nope"), | ||
} | ||
} | ||
|
||
fn rfcs_issue_1006_1() { | ||
let v = vec!["1".to_string(), "2".to_string(), "3".to_string()]; | ||
match Some(&v) { | ||
Some(iv) if iv.iter().any(|x| &x[..]=="2") => true, | ||
_ => panic!("nope"), | ||
}; | ||
} | ||
|
||
fn rfcs_issue_1006_2() { | ||
#[inline(always)] | ||
fn check<'a, I: Iterator<Item=&'a i32>>(mut i: I) -> bool { | ||
i.any(|&x| x == 2) | ||
} | ||
|
||
let slice = [1, 2, 3]; | ||
|
||
match 42 { | ||
_ if slice.iter().any(|&x| x == 2) => { true }, | ||
_ => { panic!("nope"); } | ||
}; | ||
|
||
// (This match is just illustrating how easy it was to circumvent | ||
// the checking performed for the previous `match`.) | ||
match 42 { | ||
_ if check(slice.iter()) => { true }, | ||
_ => { panic!("nope"); } | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright 2018 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. | ||
|
||
// Issue 27282: Example 2: This sidesteps the AST checks disallowing | ||
// mutable borrows in match guards by hiding the mutable borrow in a | ||
// guard behind a move (of the mutably borrowed match input) within a | ||
// closure. | ||
// | ||
// This example is not rejected by AST borrowck (and then reliably | ||
// reaches the panic code when executed, despite the compiler warning | ||
// about that match arm being unreachable. | ||
|
||
#![feature(nll)] | ||
|
||
fn main() { | ||
let b = &mut true; | ||
match b { | ||
&mut false => {}, | ||
_ if { (|| { let bar = b; *bar = false; })(); | ||
//~^ ERROR cannot move out of `b` because it is borrowed [E0505] | ||
false } => { }, | ||
&mut true => { println!("You might think we should get here"); }, | ||
//~^ ERROR use of moved value: `*b` [E0382] | ||
_ => panic!("surely we could never get here, since rustc warns it is unreachable."), | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/test/ui/issue-27282-move-match-input-into-guard.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
error[E0505]: cannot move out of `b` because it is borrowed | ||
--> $DIR/issue-27282-move-match-input-into-guard.rs:26:16 | ||
| | ||
LL | match b { | ||
| _____- | ||
| |_____| | ||
| || | ||
LL | || &mut false => {}, | ||
LL | || _ if { (|| { let bar = b; *bar = false; })(); | ||
| || ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here | ||
LL | || //~^ ERROR cannot move out of `b` because it is borrowed [E0505] | ||
... || | ||
LL | || _ => panic!("surely we could never get here, since rustc warns it is unreachable."), | ||
LL | || } | ||
| || - | ||
| ||_____| | ||
| |______borrow of `b` occurs here | ||
| borrow later used here | ||
|
||
error[E0382]: use of moved value: `*b` | ||
--> $DIR/issue-27282-move-match-input-into-guard.rs:29:14 | ||
| | ||
LL | _ if { (|| { let bar = b; *bar = false; })(); | ||
| ----------------------------------- value moved here | ||
... | ||
LL | &mut true => { println!("You might think we should get here"); }, | ||
| ^^^^ value used here after move | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
Some errors occurred: E0382, E0505. | ||
For more information about an error, try `rustc --explain E0382`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2018 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. | ||
|
||
// Issue 27282: Example 1: This sidesteps the AST checks disallowing | ||
// mutable borrows in match guards by hiding the mutable borrow in a | ||
// guard behind a move (of the ref mut pattern id) within a closure. | ||
// | ||
// This example is not rejected by AST borrowck (and then reliably | ||
// segfaults when executed). | ||
|
||
#![feature(nll)] | ||
|
||
fn main() { | ||
match Some(&4) { | ||
None => {}, | ||
ref mut foo | ||
if { (|| { let bar = foo; bar.take() })(); false } => {}, | ||
//~^ ERROR cannot move out of borrowed content [E0507] | ||
Some(s) => std::process::exit(*s), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0507]: cannot move out of borrowed content | ||
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:24:18 | ||
| | ||
LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0507`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright 2018 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. | ||
|
||
// Issue 27282: This is a variation on issue-27282-move-ref-mut-into-guard.rs | ||
// | ||
// It reborrows instead of moving the `ref mut` pattern borrow. This | ||
// means that our conservative check for mutation in guards will | ||
// reject it. But I want to make sure that we continue to reject it | ||
// (under NLL) even when that conservaive check goes away. | ||
|
||
// compile-flags: -Z disable-ast-check-for-mutation-in-guard | ||
|
||
#![feature(nll)] | ||
|
||
fn main() { | ||
let mut b = &mut true; | ||
match b { | ||
&mut false => {}, | ||
ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | ||
//~^ ERROR cannot borrow immutable item `*r` as mutable | ||
false } => { &mut *r; }, | ||
&mut true => { println!("You might think we should get here"); }, | ||
_ => panic!("surely we could never get here, since rustc warns it is unreachable."), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0596]: cannot borrow immutable item `*r` as mutable | ||
--> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:26:24 | ||
| | ||
LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0596`. |