Rollup merge of #98633 - c410-f3r:yet-another-let-chain, r=estebank

Fix last `let_chains` blocker

In order to forbid things like `let x = (let y = 1);` or `if let a = 1 && { let x = let y = 1; } {}`, the parser **HAS** to know the context of `let`.

This context thing is not a surprise in the parser because you can see **a lot** of ad hoc fixes mixing parsing logic with validation logic creating code that looks more like spaghetti with tomato sauce.

To make things even greater, a new ad hoc fix was added to only allow `let`s in a valid `let_chains` context by checking the previously processed token. This was the only solution I could think of and believe me, I thought about it for a long time 👍

In the long term, it should be preferable to segregate different responsibilities or create a more robust and cleaner parser framework.

cc https://github.com/rust-lang/rust/pull/94927
cc https://github.com/rust-lang/rust/issues/53667
This commit is contained in:
Dylan DPC 2022-07-12 17:06:33 +05:30 committed by GitHub
commit 9997c51496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 827 additions and 301 deletions

View File

@ -1393,7 +1393,9 @@ impl<'a> Parser<'a> {
self.parse_yield_expr(attrs)
} else if self.is_do_yeet() {
self.parse_yeet_expr(attrs)
} else if self.eat_keyword(kw::Let) {
} else if self.check_keyword(kw::Let) {
self.manage_let_chains_context();
self.bump();
self.parse_let_expr(attrs)
} else if self.eat_keyword(kw::Underscore) {
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs))
@ -2355,16 +2357,30 @@ impl<'a> Parser<'a> {
Ok(cond)
}
// Checks if `let` is in an invalid position like `let x = let y = 1;` or
// if the current `let` is in a let_chains context but nested in another
// expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`.
//
// This method expects that the current token is `let`.
fn manage_let_chains_context(&mut self) {
debug_assert!(matches!(self.token.kind, TokenKind::Ident(kw::Let, _)));
let is_in_a_let_chains_context_but_nested_in_other_expr = self.let_expr_allowed
&& !matches!(
self.prev_token.kind,
TokenKind::AndAnd
| TokenKind::CloseDelim(Delimiter::Brace)
| TokenKind::Ident(kw::If, _)
| TokenKind::Ident(kw::While, _)
);
if !self.let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr {
self.struct_span_err(self.token.span, "expected expression, found `let` statement")
.emit();
}
}
/// Parses a `let $pat = $expr` pseudo-expression.
/// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
if !self.let_expr_allowed {
self.struct_span_err(
self.prev_token.span,
"expected expression, found `let` statement",
)
.emit();
}
let lo = self.prev_token.span;
let pat = self.parse_pat_allow_top_alt(
None,

View File

@ -9,9 +9,11 @@ fn _if_let_guard() {
() if (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if (((let 0 = 1))) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if true && let 0 = 1 => {}
//~^ ERROR `if let` guards are experimental
@ -23,13 +25,17 @@ fn _if_let_guard() {
() if (let 0 = 1) && true => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if true && (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if (let 0 = 1) && (let 0 = 1) => {}
//~^ 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
() if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
//~^ ERROR `if let` guards are experimental
@ -38,6 +44,7 @@ fn _if_let_guard() {
//~| ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if let Range { start: _, end: _ } = (true..true) && false => {}
//~^ ERROR `if let` guards are experimental

View File

@ -1,17 +1,59 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:59:16
--> $DIR/feature-gate.rs:10:16
|
LL | () if (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:14:18
|
LL | () if (((let 0 = 1))) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:26:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:30:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:40: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:66:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:62:16
--> $DIR/feature-gate.rs:69:16
|
LL | use_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let`
--> $DIR/feature-gate.rs:71:15
--> $DIR/feature-gate.rs:78:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
@ -30,7 +72,7 @@ LL | () if let 0 = 1 => {}
= 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
--> $DIR/feature-gate.rs:18:12
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^^^^^^^^^^^^
@ -40,7 +82,7 @@ LL | () if true && let 0 = 1 => {}
= 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
--> $DIR/feature-gate.rs:22:12
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^^^^^^^^^^^^
@ -50,7 +92,7 @@ LL | () if let 0 = 1 && true => {}
= 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
--> $DIR/feature-gate.rs:40:12
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -60,7 +102,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= 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:42:12
--> $DIR/feature-gate.rs:49:12
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -70,7 +112,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
= 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:67:12
--> $DIR/feature-gate.rs:74:12
|
LL | () if let 0 = 1 => {}
| ^^^^^^^^^^^^
@ -89,7 +131,7 @@ LL | () if (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:13:18
--> $DIR/feature-gate.rs:14:18
|
LL | () if (((let 0 = 1))) => {}
| ^^^^^^^^^
@ -98,7 +140,7 @@ LL | () if (((let 0 = 1))) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:16:23
--> $DIR/feature-gate.rs:18:23
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^
@ -107,7 +149,7 @@ LL | () if true && let 0 = 1 => {}
= 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
--> $DIR/feature-gate.rs:22:15
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^
@ -116,7 +158,7 @@ LL | () if let 0 = 1 && true => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:24:16
--> $DIR/feature-gate.rs:26:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^^^^^^^
@ -125,7 +167,7 @@ LL | () if (let 0 = 1) && true => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:27:24
--> $DIR/feature-gate.rs:30:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^^^^^^^
@ -134,7 +176,7 @@ LL | () if true && (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:30:16
--> $DIR/feature-gate.rs:34:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
@ -143,7 +185,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:30:31
--> $DIR/feature-gate.rs:34:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
@ -152,7 +194,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
= 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
--> $DIR/feature-gate.rs:40:15
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -161,7 +203,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= 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
--> $DIR/feature-gate.rs:40:28
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -170,7 +212,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= 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:42
--> $DIR/feature-gate.rs:40:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -179,7 +221,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= 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:55
--> $DIR/feature-gate.rs:40:55
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -188,7 +230,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= 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:68
--> $DIR/feature-gate.rs:40:68
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -197,7 +239,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:42:15
--> $DIR/feature-gate.rs:49:15
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -206,7 +248,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:59:16
--> $DIR/feature-gate.rs:66:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^^^^^^^
@ -215,7 +257,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:62:16
--> $DIR/feature-gate.rs:69:16
|
LL | use_expr!((let 0 = 1));
| ^^^^^^^^^
@ -223,6 +265,6 @@ LL | use_expr!((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: aborting due to 25 previous errors
error: aborting due to 32 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -28,47 +28,61 @@ fn main() {}
fn _if() {
if (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (((let 0 = 1))) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (let 0 = 1) && true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if true && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (let 0 = 1) && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| 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 `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn _while() {
while (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (((let 0 = 1))) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (let 0 = 1) && true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while true && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (let 0 = 1) && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn _macros() {
@ -89,39 +103,64 @@ fn _macros() {
}
fn nested_within_if_expr() {
if &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if &let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if !let 0 = 0 {} //~ ERROR `let` expressions are not supported here
if *let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR type `bool` cannot be dereferenced
if -let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR cannot apply unary operator `-` to type `bool`
if !let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if *let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR type `bool` cannot be dereferenced
//~| ERROR expected expression, found `let` statement
if -let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR cannot apply unary operator `-` to type `bool`
//~| 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 `let` expressions are not supported here
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
if (let 0 = 0)? {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR the `?` operator can only be applied to values that implement `Try`
//~| ERROR the `?` operator can only be used in a function that returns `Result`
//~| ERROR expected expression, found `let` statement
if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here
if (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
if true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
if true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here
if true || let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if true && (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if true || (true && let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
let mut x = true;
if x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if x = let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if true..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if ..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if (let 0 = 0).. {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
// Binds as `(let ... = true)..true &&/|| false`.
if let Range { start: _, end: _ } = true..true && false {}
@ -151,42 +190,68 @@ fn nested_within_if_expr() {
if let true = let true = true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn nested_within_while_expr() {
while &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while &let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while !let 0 = 0 {} //~ ERROR `let` expressions are not supported here
while *let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR type `bool` cannot be dereferenced
while -let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR cannot apply unary operator `-` to type `bool`
while !let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while *let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR type `bool` cannot be dereferenced
//~| ERROR expected expression, found `let` statement
while -let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR cannot apply unary operator `-` to type `bool`
//~| 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 `let` expressions are not supported here
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
while (let 0 = 0)? {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR the `?` operator can only be applied to values that implement `Try`
//~| ERROR the `?` operator can only be used in a function that returns `Result`
//~| ERROR expected expression, found `let` statement
while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here
while (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
while true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
while true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here
while true || let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while true && (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while true || (true && let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
let mut x = true;
while x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while x = let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while true..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while ..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while (let 0 = 0).. {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
// Binds as `(let ... = true)..true &&/|| false`.
while let Range { start: _, end: _ } = true..true && false {}
@ -216,6 +281,7 @@ fn nested_within_while_expr() {
while let true = let true = true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn not_error_because_clarified_intent() {
@ -316,15 +382,18 @@ fn inside_const_generic_arguments() {
impl<const B: bool> A<{B}> { const O: u32 = 5; }
if let A::<{
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
true && let 1 = 1
//~^ ERROR `let` expressions are not supported here
}>::O = 5 {}
while let A::<{
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
true && let 1 = 1
//~^ ERROR `let` expressions are not supported here
}>::O = 5 {}
if A::<{
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
true && let 1 = 1
//~^ ERROR `let` expressions are not supported here
}>::O == 5 {}
// In the cases above we have `ExprKind::Block` to help us out.
@ -345,14 +414,18 @@ fn with_parenthesis() {
if (let Some(a) = opt && true) {
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt) && true {
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt) && (let Some(b) = a) {
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
}
if let Some(a) = opt && (true && true) {
}
@ -360,13 +433,18 @@ fn with_parenthesis() {
if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt && (let Some(b) = a)) && true {
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt && (true)) && true {
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
if (true && (true)) && let Some(a) = opt {

View File

@ -19,6 +19,11 @@ fn _if() {
if let Range { start: _, end: _ } = (true..true) && false {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
if let 1 = 1 && let true = { true } && false {
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~| ERROR `let` expressions in this position are unstable [E0658]
}
}
fn _while() {

View File

@ -1,17 +1,17 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:50:20
--> $DIR/feature-gate.rs:55:20
|
LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:40:17
--> $DIR/feature-gate.rs:45:17
|
LL | noop_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let`
--> $DIR/feature-gate.rs:53:15
--> $DIR/feature-gate.rs:58:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
@ -47,7 +47,25 @@ LL | if let Range { start: _, end: _ } = (true..true) && false {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:27:19
--> $DIR/feature-gate.rs:23:8
|
LL | if let 1 = 1 && let 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[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:23:21
|
LL | if let 1 = 1 && let 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[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:32:19
|
LL | while true && let 0 = 1 {}
| ^^^^^^^^^
@ -56,7 +74,7 @@ LL | while true && let 0 = 1 {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:30:11
--> $DIR/feature-gate.rs:35:11
|
LL | while let 0 = 1 && true {}
| ^^^^^^^^^
@ -65,7 +83,7 @@ LL | while let 0 = 1 && true {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:33:11
--> $DIR/feature-gate.rs:38:11
|
LL | while let Range { start: _, end: _ } = (true..true) && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -74,7 +92,7 @@ LL | while let Range { start: _, end: _ } = (true..true) && false {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:50:20
--> $DIR/feature-gate.rs:55:20
|
LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^^^^^^^
@ -83,7 +101,7 @@ LL | #[cfg(FALSE)] (let 0 = 1);
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:40:17
--> $DIR/feature-gate.rs:45:17
|
LL | noop_expr!((let 0 = 1));
| ^^^^^^^^^
@ -91,6 +109,6 @@ LL | noop_expr!((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: aborting due to 11 previous errors
error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,17 +1,45 @@
// check-pass
// known-bug
#![feature(let_chains)]
fn main() {
let _opt = Some(1i32);
#[cfg(FALSE)]
{
let _ = &&let Some(x) = Some(42);
//~^ ERROR expected expression, found `let` statement
}
#[cfg(FALSE)]
{
if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
//~^ ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
true
}
}
#[cfg(FALSE)]
{
if let Some(elem) = _opt && {
[1, 2, 3][let _ = ()];
//~^ ERROR expected expression, found `let` statement
true
} {
}
}
#[cfg(FALSE)]
{
if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
//~^ ERROR expected expression, found `let` statement
true
}
}
#[cfg(FALSE)]
{
if let a = 1 && {
let x = let y = 1;
//~^ ERROR expected expression, found `let` statement
} {
}
}
}

View File

@ -0,0 +1,38 @@
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:8:19
|
LL | let _ = &&let Some(x) = Some(42);
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:47
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:57
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:23:23
|
LL | [1, 2, 3][let _ = ()];
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:32:47
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:40:21
|
LL | let x = let y = 1;
| ^^^
error: aborting due to 6 previous errors