b011a0a13b
Previously some invalid let expressions would result in both a feature error and a parsing error. Avoid this and ensure that we only emit the parsing error when this happens.
341 lines
11 KiB
Rust
341 lines
11 KiB
Rust
// Check that we don't suggest enabling a feature for code that's
|
|
// not accepted even with that feature.
|
|
|
|
#![allow(irrefutable_let_patterns)]
|
|
|
|
use std::ops::Range;
|
|
|
|
fn main() {}
|
|
|
|
fn _if() {
|
|
if (let 0 = 1) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
if (((let 0 = 1))) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
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 2 = 3 && let 3 = 4 && let 4 = 5) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
fn _while() {
|
|
while (let 0 = 1) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while (((let 0 = 1))) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while (let 0 = 1) && true {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while true && (let 0 = 1) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while (let 0 = 1) && (let 0 = 1) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
|
|
while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
fn _macros() {
|
|
macro_rules! use_expr {
|
|
($e:expr) => {
|
|
if $e {}
|
|
while $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
|
|
}
|
|
|
|
fn nested_within_if_expr() {
|
|
if &let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
if !let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
if *let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
if -let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
fn _check_try_binds_tighter() -> Result<(), ()> {
|
|
if let 0 = 0? {}
|
|
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
|
Ok(())
|
|
}
|
|
if (let 0 = 0)? {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
if true || let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
if (true || let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
if true && (true || let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
if true || (true && let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
let mut x = true;
|
|
if x = let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
if true..(let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
if ..(let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
if (let 0 = 0).. {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
// Binds as `(let ... = true)..true &&/|| false`.
|
|
if let Range { start: _, end: _ } = true..true && false {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
if let Range { start: _, end: _ } = true..true || false {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
|
|
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
|
const F: fn() -> bool = || true;
|
|
if let Range { start: F, end } = F..|| true {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
|
|
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
|
let t = &&true;
|
|
if let Range { start: true, end } = t..&&false {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
|
|
if let true = let true = true {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
fn nested_within_while_expr() {
|
|
while &let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while !let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
while *let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
while -let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
fn _check_try_binds_tighter() -> Result<(), ()> {
|
|
while let 0 = 0? {}
|
|
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
|
Ok(())
|
|
}
|
|
while (let 0 = 0)? {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while true || let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
while (true || let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
while true && (true || let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
while true || (true && let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
let mut x = true;
|
|
while x = let 0 = 0 {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
while true..(let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
while ..(let 0 = 0) {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
while (let 0 = 0).. {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
// Binds as `(let ... = true)..true &&/|| false`.
|
|
while let Range { start: _, end: _ } = true..true && false {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
while let Range { start: _, end: _ } = true..true || false {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
|
|
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
|
const F: fn() -> bool = || true;
|
|
while let Range { start: F, end } = F..|| true {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
|
|
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
|
let t = &&true;
|
|
while let Range { start: true, end } = t..&&false {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR mismatched types
|
|
|
|
while let true = let true = true {}
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
fn not_error_because_clarified_intent() {
|
|
if let Range { start: _, end: _ } = (true..true || false) { }
|
|
|
|
if let Range { start: _, end: _ } = (true..true && false) { }
|
|
|
|
while let Range { start: _, end: _ } = (true..true || false) { }
|
|
|
|
while let Range { start: _, end: _ } = (true..true && false) { }
|
|
}
|
|
|
|
fn outside_if_and_while_expr() {
|
|
&let 0 = 0;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
!let 0 = 0;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
*let 0 = 0;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
-let 0 = 0;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
let _ = let _ = 3;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
fn _check_try_binds_tighter() -> Result<(), ()> {
|
|
let 0 = 0?;
|
|
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
|
Ok(())
|
|
}
|
|
(let 0 = 0)?;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
true || let 0 = 0;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
(true || let 0 = 0);
|
|
//~^ ERROR expected expression, found `let` statement
|
|
true && (true || let 0 = 0);
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
let mut x = true;
|
|
x = let 0 = 0;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
true..(let 0 = 0);
|
|
//~^ ERROR expected expression, found `let` statement
|
|
..(let 0 = 0);
|
|
//~^ ERROR expected expression, found `let` statement
|
|
(let 0 = 0)..;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
(let Range { start: _, end: _ } = true..true || false);
|
|
//~^ ERROR mismatched types
|
|
//~| ERROR expected expression, found `let` statement
|
|
|
|
(let true = let true = true);
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
|
|
{
|
|
#[cfg(FALSE)]
|
|
let x = true && let y = 1;
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
#[cfg(FALSE)]
|
|
{
|
|
[1, 2, 3][let _ = ()]
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
// Check function tail position.
|
|
&let 0 = 0
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
// Let's make sure that `let` inside const generic arguments are considered.
|
|
fn inside_const_generic_arguments() {
|
|
struct A<const B: bool>;
|
|
impl<const B: bool> A<{B}> { const O: u32 = 5; }
|
|
|
|
if let A::<{
|
|
true && let 1 = 1
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}>::O = 5 {}
|
|
|
|
while let A::<{
|
|
true && let 1 = 1
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}>::O = 5 {}
|
|
|
|
if A::<{
|
|
true && let 1 = 1
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}>::O == 5 {}
|
|
|
|
// In the cases above we have `ExprKind::Block` to help us out.
|
|
// Below however, we would not have a block and so an implementation might go
|
|
// from visiting expressions to types without banning `let` expressions down the tree.
|
|
// This tests ensures that we are not caught by surprise should the parser
|
|
// admit non-IDENT expressions in const generic arguments.
|
|
|
|
if A::<
|
|
true && let 1 = 1
|
|
//~^ ERROR expressions must be enclosed in braces
|
|
//~| ERROR expected expression, found `let` statement
|
|
>::O == 5 {}
|
|
}
|
|
|
|
fn with_parenthesis() {
|
|
let opt = Some(Some(1i32));
|
|
|
|
if (let Some(a) = opt && true) {
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
if (let Some(a) = opt) && true {
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
if (let Some(a) = opt) && (let Some(b) = a) {
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
}
|
|
if (let Some(a) = opt && (let Some(b) = a)) && true {
|
|
//~^ ERROR expected expression, found `let` statement
|
|
//~| ERROR expected expression, found `let` statement
|
|
}
|
|
if (let Some(a) = opt && (true)) && true {
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
|
|
#[cfg(FALSE)]
|
|
let x = (true && let y = 1);
|
|
//~^ ERROR expected expression, found `let` statement
|
|
|
|
#[cfg(FALSE)]
|
|
{
|
|
([1, 2, 3][let _ = ()])
|
|
//~^ ERROR expected expression, found `let` statement
|
|
}
|
|
}
|