Skip to content

Commit b491402

Browse files
committed
Add more if let guard tests
1 parent 078eb11 commit b491402

11 files changed

+297
-4
lines changed

tests/ui/async-await/issues/issue-66695-static-refs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// build-pass
22
// edition:2018
33

4+
#![feature(if_let_guard)]
5+
46
static A: [i32; 5] = [1, 2, 3, 4, 5];
57

68
async fn fun() {
79
let u = A[async { 1 }.await];
810
match A {
911
i if async { true }.await => (),
12+
i if let Some(1) = async { Some(1) }.await => (),
1013
_ => (),
1114
}
1215
}
@@ -18,6 +21,7 @@ fn main() {
1821
async {
1922
match A {
2023
i if async { true }.await => (),
24+
i if let Some(2) = async { Some(2) }.await => (),
2125
_ => (),
2226
}
2327
};

tests/ui/async-await/issues/issue-67611-static-mut-refs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// [drop_tracking] compile-flags: -Zdrop-tracking
66
// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
77

8+
#![feature(if_let_guard)]
9+
810
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
911

1012
fn is_send_sync<T: Send + Sync>(_: T) {}
@@ -14,6 +16,7 @@ async fn fun() {
1416
unsafe {
1517
match A {
1618
i if async { true }.await => (),
19+
i if let Some(1) = async { Some(1) }.await => (),
1720
_ => (),
1821
}
1922
}
@@ -27,6 +30,7 @@ fn main() {
2730
unsafe {
2831
match A {
2932
i if async { true }.await => (),
33+
i if let Some(2) = async { Some(2) }.await => (),
3034
_ => (),
3135
}
3236
}

tests/ui/async-await/missed-capture-issue-107414.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// check-pass
22
// edition:2018
33

4+
#![feature(if_let_guard)]
5+
46
fn main() {}
57

68
struct StructA {}
@@ -22,3 +24,10 @@ async fn ice() {
2224
_ => {}
2325
}
2426
}
27+
28+
async fn if_let() {
29+
match Some(StructB {}) {
30+
Some(struct_b) if let true = get_struct_a_async().await.fn_taking_struct_b(&struct_b) => {}
31+
_ => {}
32+
}
33+
}

tests/ui/binding/match-beginning-vert.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// run-pass
2+
3+
#![feature(if_let_guard)]
4+
25
enum Foo {
36
A,
47
B,
@@ -13,6 +16,7 @@ fn main() {
1316
match *foo {
1417
| A => println!("A"),
1518
| B | C if 1 < 2 => println!("BC!"),
19+
| D if let 1 = 1 => println!("D!"),
1620
| _ => {},
1721
}
1822
}

tests/ui/drop/dynamic-drop.rs

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// needs-unwind
33

44
#![feature(generators, generator_trait)]
5+
#![feature(if_let_guard)]
56

67
#![allow(unused_assignments)]
78
#![allow(unused_variables)]
@@ -332,6 +333,16 @@ fn move_ref_pattern(a: &Allocator) {
332333
let (ref _a, ref mut _b, _c, mut _d) = tup;
333334
}
334335

336+
fn if_let_guard(a: &Allocator, c: bool, d: i32) {
337+
let foo = if c { Some(a.alloc()) } else { None };
338+
339+
match d == 0 {
340+
false if let Some(a) = foo => { let b = a; }
341+
true if let true = { drop(foo.unwrap_or_else(|| a.alloc())); d == 1 } => {}
342+
_ => {}
343+
}
344+
}
345+
335346
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
336347
// Panic in the drop of `p` or `q` can leak
337348
let exceptions = vec![8, 9];
@@ -497,6 +508,13 @@ fn main() {
497508

498509
run_test(|a| move_ref_pattern(a));
499510

511+
run_test(|a| if_let_guard(a, true, 0));
512+
run_test(|a| if_let_guard(a, true, 1));
513+
run_test(|a| if_let_guard(a, true, 2));
514+
run_test(|a| if_let_guard(a, false, 0));
515+
run_test(|a| if_let_guard(a, false, 1));
516+
run_test(|a| if_let_guard(a, false, 2));
517+
500518
run_test(|a| {
501519
panic_after_return(a);
502520
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Ensure if let guards can be used in constant expressions.
2+
// build-pass
3+
4+
#![feature(if_let_guard)]
5+
6+
const fn match_if_let(x: Option<i32>, y: Option<i32>) -> i32 {
7+
match x {
8+
None if let Some(a @ 5) = y => a,
9+
Some(z) if let (Some(_), 12) = (y, z) => 2,
10+
_ => 3,
11+
}
12+
}
13+
14+
const ASSERTS: usize = {
15+
assert!(match_if_let(None, Some(5)) == 5);
16+
assert!(match_if_let(Some(12), Some(3)) == 2);
17+
assert!(match_if_let(None, Some(4)) == 3);
18+
assert!(match_if_let(Some(11), Some(3)) == 3);
19+
assert!(match_if_let(Some(12), None) == 3);
20+
assert!(match_if_let(None, None) == 3);
21+
0
22+
};
23+
24+
fn main() {
25+
let _: [(); ASSERTS];
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#![feature(if_let_guard)]
2+
#![feature(let_chains)]
3+
#![allow(irrefutable_let_patterns)]
4+
5+
fn same_pattern(c: bool) {
6+
let x: Box<_> = Box::new(1);
7+
8+
let v = (1, 2);
9+
10+
match v {
11+
(1, 2) if let y = x && c => (),
12+
(1, 2) if let z = x => (), //~ ERROR use of moved value: `x`
13+
_ => (),
14+
}
15+
}
16+
17+
fn same_pattern_ok(c: bool) {
18+
let x: Box<_> = Box::new(1);
19+
20+
let v = (1, 2);
21+
22+
match v {
23+
(1, 2) if c && let y = x => (),
24+
(1, 2) if let z = x => (),
25+
_ => (),
26+
}
27+
}
28+
29+
fn different_patterns(c: bool) {
30+
let x: Box<_> = Box::new(1);
31+
32+
let v = (1, 2);
33+
34+
match v {
35+
(1, _) if let y = x && c => (),
36+
(_, 2) if let z = x => (), //~ ERROR use of moved value: `x`
37+
_ => (),
38+
}
39+
}
40+
41+
fn different_patterns_ok(c: bool) {
42+
let x: Box<_> = Box::new(1);
43+
44+
let v = (1, 2);
45+
46+
match v {
47+
(1, _) if c && let y = x => (),
48+
(_, 2) if let z = x => (),
49+
_ => (),
50+
}
51+
}
52+
53+
fn or_pattern(c: bool) {
54+
let x: Box<_> = Box::new(1);
55+
56+
let v = (1, 2);
57+
58+
match v {
59+
(1, _) | (_, 2) if let y = x && c => (), //~ ERROR use of moved value: `x`
60+
_ => (),
61+
}
62+
}
63+
64+
fn or_pattern_ok(c: bool) {
65+
let x: Box<_> = Box::new(1);
66+
67+
let v = (1, 2);
68+
69+
match v {
70+
(1, _) | (_, 2) if c && let y = x => (),
71+
_ => (),
72+
}
73+
}
74+
75+
fn use_in_arm(c: bool) {
76+
let x: Box<_> = Box::new(1);
77+
78+
let v = (1, 2);
79+
80+
match v {
81+
(1, 2) if let y = x && c => false,
82+
_ => { *x == 1 }, //~ ERROR use of moved value: `x`
83+
};
84+
}
85+
86+
fn use_in_arm_ok(c: bool) {
87+
let x: Box<_> = Box::new(1);
88+
89+
let v = (1, 2);
90+
91+
match v {
92+
(1, 2) if c && let y = x => false,
93+
_ => { *x == 1 },
94+
};
95+
}
96+
97+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error[E0382]: use of moved value: `x`
2+
--> $DIR/move-guard-if-let-chain.rs:12:27
3+
|
4+
LL | let x: Box<_> = Box::new(1);
5+
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
6+
...
7+
LL | (1, 2) if let y = x && c => (),
8+
| - value moved here
9+
LL | (1, 2) if let z = x => (),
10+
| ^ value used here after move
11+
|
12+
help: borrow this binding in the pattern to avoid moving the value
13+
|
14+
LL | (1, 2) if let ref y = x && c => (),
15+
| +++
16+
17+
error[E0382]: use of moved value: `x`
18+
--> $DIR/move-guard-if-let-chain.rs:36:27
19+
|
20+
LL | let x: Box<_> = Box::new(1);
21+
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
22+
...
23+
LL | (1, _) if let y = x && c => (),
24+
| - value moved here
25+
LL | (_, 2) if let z = x => (),
26+
| ^ value used here after move
27+
|
28+
help: borrow this binding in the pattern to avoid moving the value
29+
|
30+
LL | (1, _) if let ref y = x && c => (),
31+
| +++
32+
33+
error[E0382]: use of moved value: `x`
34+
--> $DIR/move-guard-if-let-chain.rs:59:36
35+
|
36+
LL | let x: Box<_> = Box::new(1);
37+
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
38+
...
39+
LL | (1, _) | (_, 2) if let y = x && c => (),
40+
| - ^ value used here after move
41+
| |
42+
| value moved here
43+
|
44+
help: borrow this binding in the pattern to avoid moving the value
45+
|
46+
LL | (1, _) | (_, 2) if let ref y = x && c => (),
47+
| +++
48+
49+
error[E0382]: use of moved value: `x`
50+
--> $DIR/move-guard-if-let-chain.rs:82:16
51+
|
52+
LL | let x: Box<_> = Box::new(1);
53+
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
54+
...
55+
LL | (1, 2) if let y = x && c => false,
56+
| - value moved here
57+
LL | _ => { *x == 1 },
58+
| ^^ value used here after move
59+
|
60+
help: borrow this binding in the pattern to avoid moving the value
61+
|
62+
LL | (1, 2) if let ref y = x && c => false,
63+
| +++
64+
65+
error: aborting due to 4 previous errors
66+
67+
For more information about this error, try `rustc --explain E0382`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Check that borrowck knows that moves in the pattern for if-let guards
2+
// only happen when the pattern is matched.
3+
4+
// build-pass
5+
6+
#![feature(if_let_guard)]
7+
#![allow(irrefutable_let_patterns)]
8+
9+
fn same_pattern() {
10+
let x: Box<_> = Box::new(1);
11+
12+
let v = (1, 2);
13+
14+
match v {
15+
(1, 2) if let y = x => (),
16+
(1, 2) if let z = x => (),
17+
_ => (),
18+
}
19+
}
20+
21+
fn or_pattern() {
22+
let x: Box<_> = Box::new(1);
23+
24+
let v = (1, 2);
25+
26+
match v {
27+
(1, _) | (_, 2) if let y = x => (),
28+
_ => (),
29+
}
30+
}
31+
32+
fn main() {
33+
let x: Box<_> = Box::new(1);
34+
35+
let v = (1, 2);
36+
37+
match v {
38+
(1, 2) if let y = x => false,
39+
_ => { *x == 1 },
40+
};
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
3+
#![feature(if_let_guard)]
4+
5+
struct S;
6+
7+
fn get<T>() -> Option<T> {
8+
None
9+
}
10+
11+
fn main() {
12+
match get() {
13+
x if let Some(S) = x => {}
14+
_ => {}
15+
}
16+
}

0 commit comments

Comments
 (0)