summaryrefslogtreecommitdiffstats
path: root/tests/ui/rfcs/rfc-2294-if-let-guard
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfcs/rfc-2294-if-let-guard')
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs9
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs26
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs18
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr35
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs74
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr256
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs16
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs16
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs97
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr65
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs41
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs25
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr54
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs18
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs40
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs23
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs16
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr25
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs21
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr28
29 files changed, 1027 insertions, 0 deletions
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs
new file mode 100644
index 000000000..1f32e4af1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs
@@ -0,0 +1,9 @@
+#![feature(if_let_guard)]
+
+fn main() {
+ match Some(None) {
+ Some(x) if let Some(y) = x => (x, y),
+ _ => y, //~ ERROR cannot find value `y`
+ }
+ y //~ ERROR cannot find value `y`
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr
new file mode 100644
index 000000000..2463b7f3e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/bindings.rs:6:14
+ |
+LL | _ => y,
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/bindings.rs:8:5
+ |
+LL | y
+ | ^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
new file mode 100644
index 000000000..5c42c0d8b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
@@ -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];
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs
new file mode 100644
index 000000000..b4eb54139
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs
@@ -0,0 +1,18 @@
+#![feature(if_let_guard)]
+#![allow(irrefutable_let_patterns)]
+
+fn match_option(x: Option<u32>) {
+ match x {
+ //~^ ERROR non-exhaustive patterns: `None` not covered
+ Some(_) => {}
+ None if let y = x => {}
+ }
+}
+
+fn main() {
+ let x = ();
+ match x {
+ //~^ ERROR non-exhaustive patterns: `()` not covered
+ y if let z = y => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr
new file mode 100644
index 000000000..ddd08854f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr
@@ -0,0 +1,35 @@
+error[E0004]: non-exhaustive patterns: `None` not covered
+ --> $DIR/exhaustive.rs:5:11
+ |
+LL | match x {
+ | ^ pattern `None` not covered
+ |
+note: `Option<u32>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<u32>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ None if let y = x => {},
+LL + None => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `()` not covered
+ --> $DIR/exhaustive.rs:14:11
+ |
+LL | match x {
+ | ^ pattern `()` not covered
+ |
+ = note: the matched value is of type `()`
+ = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ y if let z = y => {},
+LL + () => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
new file mode 100644
index 000000000..b8c0eb3e6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -0,0 +1,74 @@
+// gate-test-if_let_guard
+
+use std::ops::Range;
+
+fn _if_let_guard() {
+ match () {
+ () if let 0 = 1 => {}
+ //~^ ERROR `if let` guards are experimental
+
+ () if (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if true && let 0 = 1 => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+
+ () if let 0 = 1 && true => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+
+ () if (let 0 = 1) && true => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if true && (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if (let 0 = 1) && (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+ //~| ERROR `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+
+ () if let Range { start: _, end: _ } = (true..true) && false => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+
+ _ => {}
+ }
+}
+
+fn _macros() {
+ macro_rules! use_expr {
+ ($e:expr) => {
+ match () {
+ () if $e => {}
+ _ => {}
+ }
+ }
+ }
+ use_expr!((let 0 = 1 && 0 == 0));
+ //~^ ERROR expected expression, found `let` statement
+ use_expr!((let 0 = 1));
+ //~^ ERROR expected expression, found `let` statement
+ match () {
+ #[cfg(FALSE)]
+ () if let 0 = 1 => {}
+ //~^ ERROR `if let` guards are experimental
+ _ => {}
+ }
+ use_expr!(let 0 = 1);
+ //~^ ERROR no rules expected the token `let`
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
new file mode 100644
index 000000000..62534b555
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
@@ -0,0 +1,256 @@
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:13:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:13:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:24:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:24:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:27:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:27:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:30:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:30:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:30:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:30:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:34:55
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:34:68
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:60:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:62:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: no rules expected the token `let`
+ --> $DIR/feature-gate.rs:70:15
+ |
+LL | macro_rules! use_expr {
+ | --------------------- when calling this macro
+...
+LL | use_expr!(let 0 = 1);
+ | ^^^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr`
+ --> $DIR/feature-gate.rs:53:10
+ |
+LL | ($e:expr) => {
+ | ^^^^^^^
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:7:12
+ |
+LL | () if let 0 = 1 => {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:16:12
+ |
+LL | () if true && let 0 = 1 => {}
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:20:12
+ |
+LL | () if let 0 = 1 && true => {}
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:34:12
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:43:12
+ |
+LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:66:12
+ |
+LL | () if let 0 = 1 => {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:16:23
+ |
+LL | () if true && let 0 = 1 => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:20:15
+ |
+LL | () if let 0 = 1 && true => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:34:15
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:34:28
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:43:15
+ |
+LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error: aborting due to 23 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs
new file mode 100644
index 000000000..792225e65
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs
@@ -0,0 +1,15 @@
+// References to by-move bindings in an if-let guard *cannot* be used after the guard.
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let x: Option<Option<String>> = Some(Some(String::new()));
+ match x {
+ Some(mut y) if let Some(ref z) = y => {
+ //~^ ERROR: cannot move out of `x.0` because it is borrowed
+ let _z: &String = z;
+ let _y: Option<String> = y;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr
new file mode 100644
index 000000000..741ae7c92
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr
@@ -0,0 +1,15 @@
+error[E0505]: cannot move out of `x.0` because it is borrowed
+ --> $DIR/guard-lifetime-1.rs:8:14
+ |
+LL | Some(mut y) if let Some(ref z) = y => {
+ | ^^^^^
+ | |
+ | move out of `x.0` occurs here
+ | borrow of `x.0` occurs here
+LL |
+LL | let _z: &String = z;
+ | - borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs
new file mode 100644
index 000000000..aa2154e3e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs
@@ -0,0 +1,16 @@
+// References to by-mutable-ref bindings in an if-let guard *can* be used after the guard.
+
+// check-pass
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let mut x: Option<Option<String>> = Some(Some(String::new()));
+ match x {
+ Some(ref mut y) if let Some(ref z) = *y => {
+ let _z: &String = z;
+ let _y: &mut Option<String> = y;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs
new file mode 100644
index 000000000..9353c9d92
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs
@@ -0,0 +1,14 @@
+// Check mutable bindings cannot be mutated by an if-let guard.
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let x: Option<Option<i32>> = Some(Some(6));
+ match x {
+ Some(mut y) if let Some(ref mut z) = y => {
+ //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ let _: &mut i32 = z;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr
new file mode 100644
index 000000000..98285f5c3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ --> $DIR/guard-mutability-1.rs:8:33
+ |
+LL | Some(mut y) if let Some(ref mut z) = y => {
+ | ^^^^^^^^^ cannot borrow as mutable
+ |
+ = note: variables bound in patterns are immutable until the end of the pattern guard
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs
new file mode 100644
index 000000000..4efa02f57
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs
@@ -0,0 +1,14 @@
+// Check mutable reference bindings cannot be mutated by an if-let guard.
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let mut x: Option<Option<i32>> = Some(Some(6));
+ match x {
+ Some(ref mut y) if let Some(ref mut z) = *y => {
+ //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ let _: &mut i32 = z;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr
new file mode 100644
index 000000000..31df8a922
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ --> $DIR/guard-mutability-2.rs:8:37
+ |
+LL | Some(ref mut y) if let Some(ref mut z) = *y => {
+ | ^^^^^^^^^ cannot borrow as mutable
+ |
+ = note: variables bound in patterns are immutable until the end of the pattern guard
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs
new file mode 100644
index 000000000..423a2cd53
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs
@@ -0,0 +1,16 @@
+// Expression macros can't expand to a let match guard.
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+macro_rules! m {
+ ($e:expr) => { let Some(x) = $e }
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn main() {
+ match () {
+ () if m!(Some(5)) => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr
new file mode 100644
index 000000000..b8065b9f5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr
@@ -0,0 +1,14 @@
+error: expected expression, found `let` statement
+ --> $DIR/macro-expanded.rs:7:20
+ |
+LL | ($e:expr) => { let Some(x) = $e }
+ | ^^^
+...
+LL | () if m!(Some(5)) => {}
+ | ----------- in this macro invocation
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs
new file mode 100644
index 000000000..5c333cd77
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs
@@ -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() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr
new file mode 100644
index 000000000..087e54244
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr
@@ -0,0 +1,65 @@
+error[E0382]: use of moved value: `x`
+ --> $DIR/move-guard-if-let-chain.rs:12:23
+ |
+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:23
+ |
+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:32
+ |
+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
+ |
+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`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
new file mode 100644
index 000000000..071b86e2e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
@@ -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 },
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
new file mode 100644
index 000000000..f12824db9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
@@ -0,0 +1,25 @@
+// Parenthesised let "expressions" are not allowed in guards
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+#[cfg(FALSE)]
+fn un_cfged() {
+ match () {
+ () if let 0 = 1 => {}
+ () if (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR expected expression, found `let` statement
+ }
+}
+
+fn main() {
+ match () {
+ () if let 0 = 1 => {}
+ () if (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR expected expression, found `let` statement
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr
new file mode 100644
index 000000000..0c16d9c54
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr
@@ -0,0 +1,54 @@
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:12:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:12:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:20:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:20:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:22:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:22:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs
new file mode 100644
index 000000000..d91b3a358
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs
@@ -0,0 +1,18 @@
+// Macros can be used for (parts of) the pattern and expression in an if let guard
+// check-pass
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+macro_rules! m {
+ (pattern $i:ident) => { Some($i) };
+ (expression $e:expr) => { $e };
+}
+
+fn main() {
+ match () {
+ () if let m!(pattern x) = m!(expression Some(4)) => {}
+ () if let [m!(pattern y)] = [Some(8 + m!(expression 4))] => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs
new file mode 100644
index 000000000..a303a0d1f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs
@@ -0,0 +1,40 @@
+// run-pass
+
+#![feature(if_let_guard)]
+
+enum Foo {
+ Bar,
+ Baz,
+ Qux(u8),
+}
+
+fn bar(x: bool) -> Foo {
+ if x { Foo::Baz } else { Foo::Bar }
+}
+
+fn baz(x: u8) -> Foo {
+ if x % 2 == 0 { Foo::Bar } else { Foo::Baz }
+}
+
+fn qux(x: u8) -> Foo {
+ Foo::Qux(x.rotate_left(1))
+}
+
+fn main() {
+ match Some((true, 3)) {
+ Some((x, _)) if let Foo::Bar = bar(x) => panic!(),
+ Some((_, x)) if let Foo::Baz = baz(x) => {},
+ _ => panic!(),
+ }
+ match Some(42) {
+ Some(x) if let Foo::Qux(y) = qux(x) => assert_eq!(y, 84),
+ _ => panic!(),
+ }
+
+ // issue #88015
+ #[allow(irrefutable_let_patterns)]
+ match () {
+ () | () if let x = 42 => assert_eq!(x, 42),
+ _ => panic!()
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs
new file mode 100644
index 000000000..dba292ef9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs
@@ -0,0 +1,23 @@
+// Check shadowing in if let guards works as expected.
+// check-pass
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+fn main() {
+ let x: Option<Option<i32>> = Some(Some(6));
+ match x {
+ Some(x) if let Some(x) = x => {
+ let _: i32 = x;
+ }
+ _ => {}
+ }
+
+ let y: Option<Option<Option<i32>>> = Some(Some(Some(-24)));
+ match y {
+ Some(y) if let Some(y) = y && let Some(y) = y => {
+ let _: i32 = y;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
new file mode 100644
index 000000000..ef7a772e6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
@@ -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 => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs
new file mode 100644
index 000000000..ad178dfa4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs
@@ -0,0 +1,15 @@
+#![feature(if_let_guard)]
+
+fn ok() -> Result<Option<bool>, ()> {
+ Ok(Some(true))
+}
+
+fn main() {
+ match ok() {
+ Ok(x) if let Err(_) = x => {},
+ //~^ ERROR mismatched types
+ Ok(x) if let 0 = x => {},
+ //~^ ERROR mismatched types
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr
new file mode 100644
index 000000000..4ce97a68a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+ --> $DIR/typeck.rs:9:22
+ |
+LL | Ok(x) if let Err(_) = x => {},
+ | ^^^^^^ - this expression has type `Option<bool>`
+ | |
+ | expected `Option<bool>`, found `Result<_, _>`
+ |
+ = note: expected enum `Option<bool>`
+ found enum `Result<_, _>`
+
+error[E0308]: mismatched types
+ --> $DIR/typeck.rs:11:22
+ |
+LL | Ok(x) if let 0 = x => {},
+ | ^ - this expression has type `Option<bool>`
+ | |
+ | expected `Option<bool>`, found integer
+ |
+ = note: expected enum `Option<bool>`
+ found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs
new file mode 100644
index 000000000..3ad1a50c6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs
@@ -0,0 +1,21 @@
+#![feature(if_let_guard)]
+
+#[deny(irrefutable_let_patterns)]
+fn irrefutable_let_guard() {
+ match Some(()) {
+ Some(x) if let () = x => {}
+ //~^ ERROR irrefutable `if let` guard
+ _ => {}
+ }
+}
+
+#[deny(unreachable_patterns)]
+fn unreachable_pattern() {
+ match Some(()) {
+ x if let None | None = x => {}
+ //~^ ERROR unreachable pattern
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
new file mode 100644
index 000000000..75f22ac8d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
@@ -0,0 +1,28 @@
+error: irrefutable `if let` guard pattern
+ --> $DIR/warns.rs:6:24
+ |
+LL | Some(x) if let () = x => {}
+ | ^^
+ |
+ = note: this pattern will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
+note: the lint level is defined here
+ --> $DIR/warns.rs:3:8
+ |
+LL | #[deny(irrefutable_let_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/warns.rs:15:25
+ |
+LL | x if let None | None = x => {}
+ | ^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/warns.rs:12:8
+ |
+LL | #[deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+