1
Fork 0

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) self.parse_yield_expr(attrs)
} else if self.is_do_yeet() { } else if self.is_do_yeet() {
self.parse_yeet_expr(attrs) 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) self.parse_let_expr(attrs)
} else if self.eat_keyword(kw::Underscore) { } else if self.eat_keyword(kw::Underscore) {
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs))
@ -2355,16 +2357,30 @@ impl<'a> Parser<'a> {
Ok(cond) 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. /// Parses a `let $pat = $expr` pseudo-expression.
/// The `let` token has already been eaten. /// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { 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 lo = self.prev_token.span;
let pat = self.parse_pat_allow_top_alt( let pat = self.parse_pat_allow_top_alt(
None, None,

View file

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

View file

@ -1,17 +1,59 @@
error: expected expression, found `let` statement 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)); LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^ | ^^^
error: expected expression, found `let` statement error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:62:16 --> $DIR/feature-gate.rs:69:16
| |
LL | use_expr!((let 0 = 1)); LL | use_expr!((let 0 = 1));
| ^^^ | ^^^
error: no rules expected the token `let` error: no rules expected the token `let`
--> $DIR/feature-gate.rs:71:15 --> $DIR/feature-gate.rs:78:15
| |
LL | macro_rules! use_expr { LL | macro_rules! use_expr {
| --------------------- when calling this macro | --------------------- 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>` = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental 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 => {} 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>` = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental 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 => {} 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>` = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental 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) => {} 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>` = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental 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 => {} 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>` = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:67:12 --> $DIR/feature-gate.rs:74:12
| |
LL | () if let 0 = 1 => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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))) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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) => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 => {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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)); 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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)); 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 = 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 = 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`. For more information about this error, try `rustc --explain E0658`.

View file

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

View file

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

View file

@ -1,17 +1,17 @@
error: expected expression, found `let` statement error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:50:20 --> $DIR/feature-gate.rs:55:20
| |
LL | #[cfg(FALSE)] (let 0 = 1); LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^ | ^^^
error: expected expression, found `let` statement error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:40:17 --> $DIR/feature-gate.rs:45:17
| |
LL | noop_expr!((let 0 = 1)); LL | noop_expr!((let 0 = 1));
| ^^^ | ^^^
error: no rules expected the token `let` error: no rules expected the token `let`
--> $DIR/feature-gate.rs:53:15 --> $DIR/feature-gate.rs:58:15
| |
LL | macro_rules! use_expr { LL | macro_rules! use_expr {
| --------------------- when calling this macro | --------------------- 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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 {} 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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); 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 = help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable 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)); 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 = 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 = 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`. For more information about this error, try `rustc --explain E0658`.

View file

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