From 5b95df4bdc330f34213812ad65cae86ced90d80c Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 1 Aug 2021 19:18:50 -0500 Subject: [PATCH] Add let-else tests --- .../let-else/let-else-bool-binop-init.fixed | 8 ++++ .../ui/let-else/let-else-bool-binop-init.rs | 8 ++++ .../let-else/let-else-bool-binop-init.stderr | 24 ++++++++++ .../let-else/let-else-brace-before-else.fixed | 26 +++++++++++ .../ui/let-else/let-else-brace-before-else.rs | 26 +++++++++++ .../let-else-brace-before-else.stderr | 46 +++++++++++++++++++ src/test/ui/let-else/let-else-check.rs | 14 ++++++ src/test/ui/let-else/let-else-check.stderr | 14 ++++++ src/test/ui/let-else/let-else-irrefutable.rs | 7 +++ .../ui/let-else/let-else-irrefutable.stderr | 12 +++++ .../ui/let-else/let-else-missing-semicolon.rs | 11 +++++ .../let-else-missing-semicolon.stderr | 18 ++++++++ .../ui/let-else/let-else-non-diverging.rs | 13 ++++++ .../ui/let-else/let-else-non-diverging.stderr | 44 ++++++++++++++++++ src/test/ui/let-else/let-else-run-pass.rs | 35 ++++++++++++++ src/test/ui/let-else/let-else-scope.rs | 7 +++ src/test/ui/let-else/let-else-scope.stderr | 9 ++++ 17 files changed, 322 insertions(+) create mode 100644 src/test/ui/let-else/let-else-bool-binop-init.fixed create mode 100644 src/test/ui/let-else/let-else-bool-binop-init.rs create mode 100644 src/test/ui/let-else/let-else-bool-binop-init.stderr create mode 100644 src/test/ui/let-else/let-else-brace-before-else.fixed create mode 100644 src/test/ui/let-else/let-else-brace-before-else.rs create mode 100644 src/test/ui/let-else/let-else-brace-before-else.stderr create mode 100644 src/test/ui/let-else/let-else-check.rs create mode 100644 src/test/ui/let-else/let-else-check.stderr create mode 100644 src/test/ui/let-else/let-else-irrefutable.rs create mode 100644 src/test/ui/let-else/let-else-irrefutable.stderr create mode 100644 src/test/ui/let-else/let-else-missing-semicolon.rs create mode 100644 src/test/ui/let-else/let-else-missing-semicolon.stderr create mode 100644 src/test/ui/let-else/let-else-non-diverging.rs create mode 100644 src/test/ui/let-else/let-else-non-diverging.stderr create mode 100644 src/test/ui/let-else/let-else-run-pass.rs create mode 100644 src/test/ui/let-else/let-else-scope.rs create mode 100644 src/test/ui/let-else/let-else-scope.stderr diff --git a/src/test/ui/let-else/let-else-bool-binop-init.fixed b/src/test/ui/let-else/let-else-bool-binop-init.fixed new file mode 100644 index 0000000000000..e47f7f23d7e07 --- /dev/null +++ b/src/test/ui/let-else/let-else-bool-binop-init.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +#![feature(let_else)] + +fn main() { + let true = (true && false) else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else` + let true = (true || false) else { return }; //~ ERROR a `||` expression cannot be directly assigned in `let...else` +} diff --git a/src/test/ui/let-else/let-else-bool-binop-init.rs b/src/test/ui/let-else/let-else-bool-binop-init.rs new file mode 100644 index 0000000000000..e443fb0d6a376 --- /dev/null +++ b/src/test/ui/let-else/let-else-bool-binop-init.rs @@ -0,0 +1,8 @@ +// run-rustfix + +#![feature(let_else)] + +fn main() { + let true = true && false else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else` + let true = true || false else { return }; //~ ERROR a `||` expression cannot be directly assigned in `let...else` +} diff --git a/src/test/ui/let-else/let-else-bool-binop-init.stderr b/src/test/ui/let-else/let-else-bool-binop-init.stderr new file mode 100644 index 0000000000000..6551e24cc83d0 --- /dev/null +++ b/src/test/ui/let-else/let-else-bool-binop-init.stderr @@ -0,0 +1,24 @@ +error: a `&&` expression cannot be directly assigned in `let...else` + --> $DIR/let-else-bool-binop-init.rs:6:16 + | +LL | let true = true && false else { return }; + | ^^^^^^^^^^^^^ + | +help: wrap the expression in parenthesis + | +LL | let true = (true && false) else { return }; + | + + + +error: a `||` expression cannot be directly assigned in `let...else` + --> $DIR/let-else-bool-binop-init.rs:7:16 + | +LL | let true = true || false else { return }; + | ^^^^^^^^^^^^^ + | +help: wrap the expression in parenthesis + | +LL | let true = (true || false) else { return }; + | + + + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/let-else/let-else-brace-before-else.fixed b/src/test/ui/let-else/let-else-brace-before-else.fixed new file mode 100644 index 0000000000000..fb4fd77791e03 --- /dev/null +++ b/src/test/ui/let-else/let-else-brace-before-else.fixed @@ -0,0 +1,26 @@ +// run-rustfix + +#![feature(let_else)] + +fn main() { + let Some(1) = ({ Some(1) }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = (loop { break Some(1) }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let 2 = 1 + (match 1 { n => n }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = (unsafe { unsafe_fn() }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; +} + +unsafe fn unsafe_fn() -> T { + unimplemented!(); +} diff --git a/src/test/ui/let-else/let-else-brace-before-else.rs b/src/test/ui/let-else/let-else-brace-before-else.rs new file mode 100644 index 0000000000000..c4c5a1ca28bbe --- /dev/null +++ b/src/test/ui/let-else/let-else-brace-before-else.rs @@ -0,0 +1,26 @@ +// run-rustfix + +#![feature(let_else)] + +fn main() { + let Some(1) = { Some(1) } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = loop { break Some(1) } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let 2 = 1 + match 1 { n => n } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = unsafe { unsafe_fn() } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; +} + +unsafe fn unsafe_fn() -> T { + unimplemented!(); +} diff --git a/src/test/ui/let-else/let-else-brace-before-else.stderr b/src/test/ui/let-else/let-else-brace-before-else.stderr new file mode 100644 index 0000000000000..eac029c848b20 --- /dev/null +++ b/src/test/ui/let-else/let-else-brace-before-else.stderr @@ -0,0 +1,46 @@ +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:6:29 + | +LL | let Some(1) = { Some(1) } else { + | ^ + | +help: try wrapping the expression in parenthesis + | +LL | let Some(1) = ({ Some(1) }) else { + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:10:40 + | +LL | let Some(1) = loop { break Some(1) } else { + | ^ + | +help: try wrapping the expression in parenthesis + | +LL | let Some(1) = (loop { break Some(1) }) else { + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:14:34 + | +LL | let 2 = 1 + match 1 { n => n } else { + | ^ + | +help: try wrapping the expression in parenthesis + | +LL | let 2 = 1 + (match 1 { n => n }) else { + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:18:40 + | +LL | let Some(1) = unsafe { unsafe_fn() } else { + | ^ + | +help: try wrapping the expression in parenthesis + | +LL | let Some(1) = (unsafe { unsafe_fn() }) else { + | + + + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/let-else/let-else-check.rs b/src/test/ui/let-else/let-else-check.rs new file mode 100644 index 0000000000000..ab763447ef7e1 --- /dev/null +++ b/src/test/ui/let-else/let-else-check.rs @@ -0,0 +1,14 @@ +#![feature(let_else)] + +#![deny(unused_variables)] + +fn main() { + // type annotation, attributes + #[allow(unused_variables)] + let Some(_): Option = Some(Default::default()) else { + let x = 1; // OK + return; + }; + + let x = 1; //~ ERROR unused variable: `x` +} diff --git a/src/test/ui/let-else/let-else-check.stderr b/src/test/ui/let-else/let-else-check.stderr new file mode 100644 index 0000000000000..50e54d320b006 --- /dev/null +++ b/src/test/ui/let-else/let-else-check.stderr @@ -0,0 +1,14 @@ +error: unused variable: `x` + --> $DIR/let-else-check.rs:13:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/let-else-check.rs:3:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/let-else/let-else-irrefutable.rs b/src/test/ui/let-else/let-else-irrefutable.rs new file mode 100644 index 0000000000000..b1e09a1248ff7 --- /dev/null +++ b/src/test/ui/let-else/let-else-irrefutable.rs @@ -0,0 +1,7 @@ +// check-pass + +#![feature(let_else)] + +fn main() { + let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern +} diff --git a/src/test/ui/let-else/let-else-irrefutable.stderr b/src/test/ui/let-else/let-else-irrefutable.stderr new file mode 100644 index 0000000000000..e030c50d45dcf --- /dev/null +++ b/src/test/ui/let-else/let-else-irrefutable.stderr @@ -0,0 +1,12 @@ +warning: irrefutable `let...else` pattern + --> $DIR/let-else-irrefutable.rs:6:5 + | +LL | let x = 1 else { return }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: 1 warning emitted + diff --git a/src/test/ui/let-else/let-else-missing-semicolon.rs b/src/test/ui/let-else/let-else-missing-semicolon.rs new file mode 100644 index 0000000000000..ed9d79f1ebde9 --- /dev/null +++ b/src/test/ui/let-else/let-else-missing-semicolon.rs @@ -0,0 +1,11 @@ +#![feature(let_else)] + +fn main() { + let Some(x) = Some(1) else { + return; + } //~ ERROR expected `;`, found keyword `let` + let _ = ""; + let Some(x) = Some(1) else { + panic!(); + } //~ ERROR expected `;`, found `}` +} diff --git a/src/test/ui/let-else/let-else-missing-semicolon.stderr b/src/test/ui/let-else/let-else-missing-semicolon.stderr new file mode 100644 index 0000000000000..1818a0b126348 --- /dev/null +++ b/src/test/ui/let-else/let-else-missing-semicolon.stderr @@ -0,0 +1,18 @@ +error: expected `;`, found keyword `let` + --> $DIR/let-else-missing-semicolon.rs:6:6 + | +LL | } + | ^ help: add `;` here +LL | let _ = ""; + | --- unexpected token + +error: expected `;`, found `}` + --> $DIR/let-else-missing-semicolon.rs:10:6 + | +LL | } + | ^ help: add `;` here +LL | } + | - unexpected token + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/let-else/let-else-non-diverging.rs b/src/test/ui/let-else/let-else-non-diverging.rs new file mode 100644 index 0000000000000..a1cee335aeeba --- /dev/null +++ b/src/test/ui/let-else/let-else-non-diverging.rs @@ -0,0 +1,13 @@ +#![feature(let_else)] + +fn main() { + let Some(x) = Some(1) else { //~ ERROR does not diverge + Some(2) + }; + let Some(x) = Some(1) else { //~ ERROR does not diverge + if 1 == 1 { + panic!(); + } + }; + let Some(x) = Some(1) else { Some(2) }; //~ ERROR does not diverge +} diff --git a/src/test/ui/let-else/let-else-non-diverging.stderr b/src/test/ui/let-else/let-else-non-diverging.stderr new file mode 100644 index 0000000000000..fd5a18ce7ea51 --- /dev/null +++ b/src/test/ui/let-else/let-else-non-diverging.stderr @@ -0,0 +1,44 @@ +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:12:32 + | +LL | let Some(x) = Some(1) else { Some(2) }; + | ^^^^^^^^^^^ expected `!`, found enum `Option` + | + = note: expected type `!` + found type `Option<{integer}>` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:7:32 + | +LL | let Some(x) = Some(1) else { + | ________________________________^ +LL | | if 1 == 1 { +LL | | panic!(); +LL | | } +LL | | }; + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found type `()` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:4:32 + | +LL | let Some(x) = Some(1) else { + | ________________________________^ +LL | | Some(2) +LL | | }; + | |_____^ expected `!`, found enum `Option` + | + = note: expected type `!` + found type `Option<{integer}>` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/let-else/let-else-run-pass.rs b/src/test/ui/let-else/let-else-run-pass.rs new file mode 100644 index 0000000000000..5d96623236dab --- /dev/null +++ b/src/test/ui/let-else/let-else-run-pass.rs @@ -0,0 +1,35 @@ +// run-pass + +#![feature(let_else)] + +fn main() { + #[allow(dead_code)] + enum MyEnum { + A(String), + B { f: String }, + C, + } + // ref binding to non-copy value and or-pattern + let (MyEnum::A(ref x) | MyEnum::B { f: ref x }) = (MyEnum::B { f: String::new() }) else { + panic!(); + }; + assert_eq!(x, ""); + + // nested let-else + let mut x = 1; + loop { + let 4 = x else { + let 3 = x else { + x += 1; + continue; + }; + break; + }; + panic!(); + } + assert_eq!(x, 3); + + // else return + let Some(1) = Some(2) else { return }; + panic!(); +} diff --git a/src/test/ui/let-else/let-else-scope.rs b/src/test/ui/let-else/let-else-scope.rs new file mode 100644 index 0000000000000..f17682db4c3bd --- /dev/null +++ b/src/test/ui/let-else/let-else-scope.rs @@ -0,0 +1,7 @@ +#![feature(let_else)] + +fn main() { + let Some(x) = Some(2) else { + panic!("{}", x); //~ ERROR cannot find value `x` in this scope + }; +} diff --git a/src/test/ui/let-else/let-else-scope.stderr b/src/test/ui/let-else/let-else-scope.stderr new file mode 100644 index 0000000000000..4b3936eac4bd5 --- /dev/null +++ b/src/test/ui/let-else/let-else-scope.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/let-else-scope.rs:5:22 + | +LL | panic!("{}", x); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`.