Skip to content

Commit d3c3c17

Browse files
committed
Add more tests for if_let_guard
1 parent b4d09f3 commit d3c3c17

15 files changed

+298
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(if_let_guard)]
2+
#![allow(irrefutable_let_patterns)]
3+
4+
fn match_option(x: Option<u32>) {
5+
match x {
6+
//~^ ERROR non-exhaustive patterns: `None` not covered
7+
Some(_) => {}
8+
None if let y = x => {}
9+
}
10+
}
11+
12+
fn main() {
13+
let x = ();
14+
match x {
15+
//~^ ERROR non-exhaustive patterns: `()` not covered
16+
y if let z = y => {}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0004]: non-exhaustive patterns: `None` not covered
2+
--> $DIR/exhaustive.rs:5:11
3+
|
4+
LL | match x {
5+
| ^ pattern `None` not covered
6+
|
7+
note: `Option<u32>` defined here
8+
--> $SRC_DIR/core/src/option.rs:LL:COL
9+
::: $SRC_DIR/core/src/option.rs:LL:COL
10+
|
11+
= note: not covered
12+
= note: the matched value is of type `Option<u32>`
13+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
14+
|
15+
LL ~ None if let y = x => {},
16+
LL + None => todo!()
17+
|
18+
19+
error[E0004]: non-exhaustive patterns: `()` not covered
20+
--> $DIR/exhaustive.rs:14:11
21+
|
22+
LL | match x {
23+
| ^ pattern `()` not covered
24+
|
25+
= note: the matched value is of type `()`
26+
= note: match arms with guards don't count towards exhaustivity
27+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
28+
|
29+
LL ~ y if let z = y => {},
30+
LL + () => todo!()
31+
|
32+
33+
error: aborting due to 2 previous errors
34+
35+
For more information about this error, try `rustc --explain E0004`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// References to by-move bindings in an if-let guard *cannot* be used after the guard.
2+
3+
#![feature(if_let_guard)]
4+
5+
fn main() {
6+
let x: Option<Option<String>> = Some(Some(String::new()));
7+
match x {
8+
Some(mut y) if let Some(ref z) = y => {
9+
//~^ ERROR: cannot move out of `x.0` because it is borrowed
10+
let _z: &String = z;
11+
let _y: Option<String> = y;
12+
}
13+
_ => {}
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0505]: cannot move out of `x.0` because it is borrowed
2+
--> $DIR/guard-lifetime-1.rs:8:14
3+
|
4+
LL | Some(mut y) if let Some(ref z) = y => {
5+
| ^^^^^
6+
| |
7+
| move out of `x.0` occurs here
8+
| borrow of `x.0` occurs here
9+
LL |
10+
LL | let _z: &String = z;
11+
| - borrow later used here
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0505`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// References to by-mutable-ref bindings in an if-let guard *can* be used after the guard.
2+
3+
// check-pass
4+
5+
#![feature(if_let_guard)]
6+
7+
fn main() {
8+
let mut x: Option<Option<String>> = Some(Some(String::new()));
9+
match x {
10+
Some(ref mut y) if let Some(ref z) = *y => {
11+
let _z: &String = z;
12+
let _y: &mut Option<String> = y;
13+
}
14+
_ => {}
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Check mutable bindings cannot be mutated by an if-let guard.
2+
3+
#![feature(if_let_guard)]
4+
5+
fn main() {
6+
let x: Option<Option<i32>> = Some(Some(6));
7+
match x {
8+
Some(mut y) if let Some(ref mut z) = y => {
9+
//~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
10+
let _: &mut i32 = z;
11+
}
12+
_ => {}
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
2+
--> $DIR/guard-mutability-1.rs:8:33
3+
|
4+
LL | Some(mut y) if let Some(ref mut z) = y => {
5+
| ^^^^^^^^^ cannot borrow as mutable
6+
|
7+
= note: variables bound in patterns are immutable until the end of the pattern guard
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0596`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Check mutable reference bindings cannot be mutated by an if-let guard.
2+
3+
#![feature(if_let_guard)]
4+
5+
fn main() {
6+
let mut x: Option<Option<i32>> = Some(Some(6));
7+
match x {
8+
Some(ref mut y) if let Some(ref mut z) = *y => {
9+
//~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
10+
let _: &mut i32 = z;
11+
}
12+
_ => {}
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
2+
--> $DIR/guard-mutability-2.rs:8:37
3+
|
4+
LL | Some(ref mut y) if let Some(ref mut z) = *y => {
5+
| ^^^^^^^^^ cannot borrow as mutable
6+
|
7+
= note: variables bound in patterns are immutable until the end of the pattern guard
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0596`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Expression macros can't expand to a let match guard.
2+
3+
#![feature(if_let_guard)]
4+
#![feature(let_chains)]
5+
6+
macro_rules! m {
7+
($e:expr) => { let Some(x) = $e }
8+
//~^ ERROR expected expression, found `let` statement
9+
}
10+
11+
fn main() {
12+
match () {
13+
() if m!(Some(5)) => {}
14+
_ => {}
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: expected expression, found `let` statement
2+
--> $DIR/macro-expanded.rs:7:20
3+
|
4+
LL | ($e:expr) => { let Some(x) = $e }
5+
| ^^^
6+
...
7+
LL | () if m!(Some(5)) => {}
8+
| ----------- in this macro invocation
9+
|
10+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
12+
error: aborting due to previous error
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Parenthesised let "expressions" are not allowed in guards
2+
3+
#![feature(if_let_guard)]
4+
#![feature(let_chains)]
5+
6+
#[cfg(FALSE)]
7+
fn un_cfged() {
8+
match () {
9+
() if let 0 = 1 => {}
10+
() if (let 0 = 1) => {}
11+
//~^ ERROR expected expression, found `let` statement
12+
() if (((let 0 = 1))) => {}
13+
//~^ ERROR expected expression, found `let` statement
14+
}
15+
}
16+
17+
fn main() {
18+
match () {
19+
() if let 0 = 1 => {}
20+
() if (let 0 = 1) => {}
21+
//~^ ERROR expected expression, found `let` statement
22+
//~| ERROR `let` expressions are not supported here
23+
() if (((let 0 = 1))) => {}
24+
//~^ ERROR expected expression, found `let` statement
25+
//~| ERROR `let` expressions are not supported here
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error: expected expression, found `let` statement
2+
--> $DIR/parens.rs:10:16
3+
|
4+
LL | () if (let 0 = 1) => {}
5+
| ^^^
6+
7+
error: expected expression, found `let` statement
8+
--> $DIR/parens.rs:12:18
9+
|
10+
LL | () if (((let 0 = 1))) => {}
11+
| ^^^
12+
13+
error: expected expression, found `let` statement
14+
--> $DIR/parens.rs:20:16
15+
|
16+
LL | () if (let 0 = 1) => {}
17+
| ^^^
18+
19+
error: expected expression, found `let` statement
20+
--> $DIR/parens.rs:23:18
21+
|
22+
LL | () if (((let 0 = 1))) => {}
23+
| ^^^
24+
25+
error: `let` expressions are not supported here
26+
--> $DIR/parens.rs:20:16
27+
|
28+
LL | () if (let 0 = 1) => {}
29+
| ^^^^^^^^^
30+
|
31+
= note: only supported directly in conditions of `if` and `while` expressions
32+
note: `let`s wrapped in parentheses are not supported in a context with let chains
33+
--> $DIR/parens.rs:20:16
34+
|
35+
LL | () if (let 0 = 1) => {}
36+
| ^^^^^^^^^
37+
38+
error: `let` expressions are not supported here
39+
--> $DIR/parens.rs:23:18
40+
|
41+
LL | () if (((let 0 = 1))) => {}
42+
| ^^^^^^^^^
43+
|
44+
= note: only supported directly in conditions of `if` and `while` expressions
45+
note: `let`s wrapped in parentheses are not supported in a context with let chains
46+
--> $DIR/parens.rs:23:18
47+
|
48+
LL | () if (((let 0 = 1))) => {}
49+
| ^^^^^^^^^
50+
51+
error: aborting due to 6 previous errors
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Macros can be used for (parts of) the pattern and expression in an if let guard
2+
// check-pass
3+
4+
#![feature(if_let_guard)]
5+
#![feature(let_chains)]
6+
7+
macro_rules! m {
8+
(pattern $i:ident) => { Some($i) };
9+
(expression $e:expr) => { $e };
10+
}
11+
12+
fn main() {
13+
match () {
14+
() if let m!(pattern x) = m!(expression Some(4)) => {}
15+
() if let [m!(pattern y)] = [Some(8 + m!(expression 4))] => {}
16+
_ => {}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Check shadowing in if let guards works as expected.
2+
// check-pass
3+
4+
#![feature(if_let_guard)]
5+
#![feature(let_chains)]
6+
7+
fn main() {
8+
let x: Option<Option<i32>> = Some(Some(6));
9+
match x {
10+
Some(x) if let Some(x) = x => {
11+
let _: i32 = x;
12+
}
13+
_ => {}
14+
}
15+
16+
let y: Option<Option<Option<i32>>> = Some(Some(Some(-24)));
17+
match y {
18+
Some(y) if let Some(y) = y && let Some(y) = y => {
19+
let _: i32 = y;
20+
}
21+
_ => {}
22+
}
23+
}

0 commit comments

Comments
 (0)