mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 14:01:51 +00:00
Add more if let guard tests
This commit is contained in:
parent
078eb1120a
commit
b49140295c
@ -1,12 +1,15 @@
|
||||
// build-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
static A: [i32; 5] = [1, 2, 3, 4, 5];
|
||||
|
||||
async fn fun() {
|
||||
let u = A[async { 1 }.await];
|
||||
match A {
|
||||
i if async { true }.await => (),
|
||||
i if let Some(1) = async { Some(1) }.await => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -18,6 +21,7 @@ fn main() {
|
||||
async {
|
||||
match A {
|
||||
i if async { true }.await => (),
|
||||
i if let Some(2) = async { Some(2) }.await => (),
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
|
@ -5,6 +5,8 @@
|
||||
// [drop_tracking] compile-flags: -Zdrop-tracking
|
||||
// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
|
||||
|
||||
fn is_send_sync<T: Send + Sync>(_: T) {}
|
||||
@ -14,6 +16,7 @@ async fn fun() {
|
||||
unsafe {
|
||||
match A {
|
||||
i if async { true }.await => (),
|
||||
i if let Some(1) = async { Some(1) }.await => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -27,6 +30,7 @@ fn main() {
|
||||
unsafe {
|
||||
match A {
|
||||
i if async { true }.await => (),
|
||||
i if let Some(2) = async { Some(2) }.await => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
// check-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct StructA {}
|
||||
@ -22,3 +24,10 @@ async fn ice() {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
async fn if_let() {
|
||||
match Some(StructB {}) {
|
||||
Some(struct_b) if let true = get_struct_a_async().await.fn_taking_struct_b(&struct_b) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
@ -13,6 +16,7 @@ fn main() {
|
||||
match *foo {
|
||||
| A => println!("A"),
|
||||
| B | C if 1 < 2 => println!("BC!"),
|
||||
| D if let 1 = 1 => println!("D!"),
|
||||
| _ => {},
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// needs-unwind
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
#![allow(unused_assignments)]
|
||||
#![allow(unused_variables)]
|
||||
@ -332,6 +333,16 @@ fn move_ref_pattern(a: &Allocator) {
|
||||
let (ref _a, ref mut _b, _c, mut _d) = tup;
|
||||
}
|
||||
|
||||
fn if_let_guard(a: &Allocator, c: bool, d: i32) {
|
||||
let foo = if c { Some(a.alloc()) } else { None };
|
||||
|
||||
match d == 0 {
|
||||
false if let Some(a) = foo => { let b = a; }
|
||||
true if let true = { drop(foo.unwrap_or_else(|| a.alloc())); d == 1 } => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
|
||||
// Panic in the drop of `p` or `q` can leak
|
||||
let exceptions = vec![8, 9];
|
||||
@ -497,6 +508,13 @@ fn main() {
|
||||
|
||||
run_test(|a| move_ref_pattern(a));
|
||||
|
||||
run_test(|a| if_let_guard(a, true, 0));
|
||||
run_test(|a| if_let_guard(a, true, 1));
|
||||
run_test(|a| if_let_guard(a, true, 2));
|
||||
run_test(|a| if_let_guard(a, false, 0));
|
||||
run_test(|a| if_let_guard(a, false, 1));
|
||||
run_test(|a| if_let_guard(a, false, 2));
|
||||
|
||||
run_test(|a| {
|
||||
panic_after_return(a);
|
||||
});
|
||||
|
26
tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
Normal file
26
tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Ensure if let guards can be used in constant expressions.
|
||||
// build-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
const fn match_if_let(x: Option<i32>, y: Option<i32>) -> i32 {
|
||||
match x {
|
||||
None if let Some(a @ 5) = y => a,
|
||||
Some(z) if let (Some(_), 12) = (y, z) => 2,
|
||||
_ => 3,
|
||||
}
|
||||
}
|
||||
|
||||
const ASSERTS: usize = {
|
||||
assert!(match_if_let(None, Some(5)) == 5);
|
||||
assert!(match_if_let(Some(12), Some(3)) == 2);
|
||||
assert!(match_if_let(None, Some(4)) == 3);
|
||||
assert!(match_if_let(Some(11), Some(3)) == 3);
|
||||
assert!(match_if_let(Some(12), None) == 3);
|
||||
assert!(match_if_let(None, None) == 3);
|
||||
0
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let _: [(); ASSERTS];
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
#![allow(irrefutable_let_patterns)]
|
||||
|
||||
fn same_pattern(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, 2) if let y = x && c => (),
|
||||
(1, 2) if let z = x => (), //~ ERROR use of moved value: `x`
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn same_pattern_ok(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, 2) if c && let y = x => (),
|
||||
(1, 2) if let z = x => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn different_patterns(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, _) if let y = x && c => (),
|
||||
(_, 2) if let z = x => (), //~ ERROR use of moved value: `x`
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn different_patterns_ok(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, _) if c && let y = x => (),
|
||||
(_, 2) if let z = x => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn or_pattern(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, _) | (_, 2) if let y = x && c => (), //~ ERROR use of moved value: `x`
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn or_pattern_ok(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, _) | (_, 2) if c && let y = x => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn use_in_arm(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, 2) if let y = x && c => false,
|
||||
_ => { *x == 1 }, //~ ERROR use of moved value: `x`
|
||||
};
|
||||
}
|
||||
|
||||
fn use_in_arm_ok(c: bool) {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, 2) if c && let y = x => false,
|
||||
_ => { *x == 1 },
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,67 @@
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:12:27
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | (1, 2) if let y = x && c => (),
|
||||
| - value moved here
|
||||
LL | (1, 2) if let z = x => (),
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | (1, 2) if let ref y = x && c => (),
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:36:27
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | (1, _) if let y = x && c => (),
|
||||
| - value moved here
|
||||
LL | (_, 2) if let z = x => (),
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | (1, _) if let ref y = x && c => (),
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:59:36
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | (1, _) | (_, 2) if let y = x && c => (),
|
||||
| - ^ value used here after move
|
||||
| |
|
||||
| value moved here
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | (1, _) | (_, 2) if let ref y = x && c => (),
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:82:16
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | (1, 2) if let y = x && c => false,
|
||||
| - value moved here
|
||||
LL | _ => { *x == 1 },
|
||||
| ^^ value used here after move
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | (1, 2) if let ref y = x && c => false,
|
||||
| +++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
41
tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
Normal file
41
tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// Check that borrowck knows that moves in the pattern for if-let guards
|
||||
// only happen when the pattern is matched.
|
||||
|
||||
// build-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(irrefutable_let_patterns)]
|
||||
|
||||
fn same_pattern() {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, 2) if let y = x => (),
|
||||
(1, 2) if let z = x => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn or_pattern() {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, _) | (_, 2) if let y = x => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: Box<_> = Box::new(1);
|
||||
|
||||
let v = (1, 2);
|
||||
|
||||
match v {
|
||||
(1, 2) if let y = x => false,
|
||||
_ => { *x == 1 },
|
||||
};
|
||||
}
|
16
tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
Normal file
16
tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
struct S;
|
||||
|
||||
fn get<T>() -> Option<T> {
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match get() {
|
||||
x if let Some(S) = x => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
@ -2,25 +2,32 @@
|
||||
|
||||
#![allow(unused_must_use)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
#![allow(path_statements)]
|
||||
#![allow(unreachable_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
fn id(x: bool) -> bool { x }
|
||||
fn id(x: bool) -> bool {
|
||||
x
|
||||
}
|
||||
|
||||
fn call_id() {
|
||||
let c = panic!();
|
||||
id(c);
|
||||
}
|
||||
|
||||
fn call_id_2() { id(true) && id(return); }
|
||||
fn call_id_2() {
|
||||
id(true) && id(return);
|
||||
}
|
||||
|
||||
fn call_id_3() { id(return) && id(return); }
|
||||
fn call_id_3() {
|
||||
id(return) && id(return);
|
||||
}
|
||||
|
||||
fn ret_guard() {
|
||||
match 2 {
|
||||
x if (return) => { x; }
|
||||
x if let true = return => { x; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user