mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-02 10:04:23 +00:00
parent
5eebd36c93
commit
98d5e134f9
@ -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"); }
|
||||
};
|
||||
}
|
33
src/test/ui/issue-27282-move-match-input-into-guard.rs
Normal file
33
src/test/ui/issue-27282-move-match-input-into-guard.rs
Normal file
@ -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
src/test/ui/issue-27282-move-match-input-into-guard.stderr
Normal file
32
src/test/ui/issue-27282-move-match-input-into-guard.stderr
Normal file
@ -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`.
|
28
src/test/ui/issue-27282-move-ref-mut-into-guard.rs
Normal file
28
src/test/ui/issue-27282-move-ref-mut-into-guard.rs
Normal file
@ -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),
|
||||
}
|
||||
}
|
9
src/test/ui/issue-27282-move-ref-mut-into-guard.stderr
Normal file
9
src/test/ui/issue-27282-move-ref-mut-into-guard.stderr
Normal file
@ -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`.
|
32
src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs
Normal file
32
src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs
Normal file
@ -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."),
|
||||
}
|
||||
}
|
9
src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr
Normal file
9
src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user