1
Fork 0

[rustc_parse] Forbid lets in certain places

This commit is contained in:
Caio 2022-06-25 08:08:38 -03:00
parent e02d645110
commit 747586732b
13 changed files with 468 additions and 196 deletions

View file

@ -7,6 +7,7 @@ use super::{
}; };
use crate::maybe_recover_from_interpolated_ty_qpath; use crate::maybe_recover_from_interpolated_ty_qpath;
use core::mem;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::Spacing; use rustc_ast::tokenstream::Spacing;
@ -26,7 +27,6 @@ use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Pos}; use rustc_span::{BytePos, Pos};
use std::mem;
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
/// dropped into the token stream, which happens while parsing the result of /// dropped into the token stream, which happens while parsing the result of
@ -2343,7 +2343,9 @@ impl<'a> Parser<'a> {
/// Parses the condition of a `if` or `while` expression. /// Parses the condition of a `if` or `while` expression.
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> { fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let cond = self.with_let_management(true, |local_self| {
local_self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)
})?;
if let ExprKind::Let(..) = cond.kind { if let ExprKind::Let(..) = cond.kind {
// Remove the last feature gating of a `let` expression since it's stable. // Remove the last feature gating of a `let` expression since it's stable.
@ -2356,6 +2358,13 @@ impl<'a> Parser<'a> {
/// 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,
@ -2672,6 +2681,8 @@ impl<'a> Parser<'a> {
} }
pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
// Used to check the `let_chains` and `if_let_guard` features mostly by scaning
// `&&` tokens.
fn check_let_expr(expr: &Expr) -> (bool, bool) { fn check_let_expr(expr: &Expr) -> (bool, bool) {
match expr.kind { match expr.kind {
ExprKind::Binary(_, ref lhs, ref rhs) => { ExprKind::Binary(_, ref lhs, ref rhs) => {
@ -2694,7 +2705,7 @@ impl<'a> Parser<'a> {
)?; )?;
let guard = if this.eat_keyword(kw::If) { let guard = if this.eat_keyword(kw::If) {
let if_span = this.prev_token.span; let if_span = this.prev_token.span;
let cond = this.parse_expr()?; let cond = this.with_let_management(true, |local_this| local_this.parse_expr())?;
let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond); let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
if has_let_expr { if has_let_expr {
if does_not_have_bin_op { if does_not_have_bin_op {
@ -3256,4 +3267,17 @@ impl<'a> Parser<'a> {
Ok((res, trailing)) Ok((res, trailing))
}) })
} }
// Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then
// sets the internal `let_expr_allowed` back to its original value.
fn with_let_management<T>(
&mut self,
let_expr_allowed: bool,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let last_let_expr_allowed = mem::replace(&mut self.let_expr_allowed, let_expr_allowed);
let rslt = f(self);
self.let_expr_allowed = last_let_expr_allowed;
rslt
}
} }

View file

@ -147,12 +147,15 @@ pub struct Parser<'a> {
/// This allows us to recover when the user forget to add braces around /// This allows us to recover when the user forget to add braces around
/// multiple statements in the closure body. /// multiple statements in the closure body.
pub current_closure: Option<ClosureSpans>, pub current_closure: Option<ClosureSpans>,
/// Used to track where `let`s are allowed. For example, `if true && let 1 = 1` is valid
/// but `[1, 2, 3][let _ = ()]` is not.
let_expr_allowed: bool,
} }
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure // This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
// it doesn't unintentionally get bigger. // it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Parser<'_>, 328); rustc_data_structures::static_assert_size!(Parser<'_>, 336);
/// Stores span information about a closure. /// Stores span information about a closure.
#[derive(Clone)] #[derive(Clone)]
@ -455,6 +458,7 @@ impl<'a> Parser<'a> {
inner_attr_ranges: Default::default(), inner_attr_ranges: Default::default(),
}, },
current_closure: None, current_closure: None,
let_expr_allowed: false,
}; };
// Make parser point to the first token. // Make parser point to the first token.

View file

@ -1,6 +1,7 @@
struct Bug<A = [(); (let a = (), 1).1]> { struct Bug<A = [(); (let a = (), 1).1]> {
//~^ `let` expressions are not supported here //~^ `let` expressions are not supported here
//~^^ `let` expressions in this position are unstable [E0658] //~| `let` expressions in this position are unstable [E0658]
//~| expected expression, found `let` statement
a: A a: A
} }

View file

@ -1,3 +1,9 @@
error: expected expression, found `let` statement
--> $DIR/issue-92893.rs:1:22
|
LL | struct Bug<A = [(); (let a = (), 1).1]> {
| ^^^
error: `let` expressions are not supported here error: `let` expressions are not supported here
--> $DIR/issue-92893.rs:1:22 --> $DIR/issue-92893.rs:1:22
| |
@ -15,6 +21,6 @@ LL | struct Bug<A = [(); (let a = (), 1).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 2 previous errors error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View file

@ -58,8 +58,10 @@ fn _macros() {
} }
use_expr!((let 0 = 1 && 0 == 0)); use_expr!((let 0 = 1 && 0 == 0));
//~^ ERROR `let` expressions in this position are unstable //~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
use_expr!((let 0 = 1)); use_expr!((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
match () { match () {
#[cfg(FALSE)] #[cfg(FALSE)]
() if let 0 = 1 => {} () if let 0 = 1 => {}

View file

@ -1,5 +1,17 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:59:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:62:16
|
LL | use_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let` error: no rules expected the token `let`
--> $DIR/feature-gate.rs:69:15 --> $DIR/feature-gate.rs:71:15
| |
LL | macro_rules! use_expr { LL | macro_rules! use_expr {
| --------------------- when calling this macro | --------------------- when calling this macro
@ -58,7 +70,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:65:12 --> $DIR/feature-gate.rs:67:12
| |
LL | () if let 0 = 1 => {} LL | () if let 0 = 1 => {}
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
@ -203,7 +215,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:61:16 --> $DIR/feature-gate.rs:62:16
| |
LL | use_expr!((let 0 = 1)); LL | use_expr!((let 0 = 1));
| ^^^^^^^^^ | ^^^^^^^^^
@ -211,6 +223,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 23 previous errors error: aborting due to 25 previous errors
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View file

@ -81,9 +81,11 @@ fn _macros() {
use_expr!((let 0 = 1 && 0 == 0)); use_expr!((let 0 = 1 && 0 == 0));
//~^ 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
use_expr!((let 0 = 1)); use_expr!((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
} }
fn nested_within_if_expr() { fn nested_within_if_expr() {
@ -147,7 +149,8 @@ fn nested_within_if_expr() {
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR mismatched types //~| ERROR mismatched types
if let true = let true = true {} //~ ERROR `let` expressions are not supported here if let true = let true = true {}
//~^ ERROR `let` expressions are not supported here
} }
fn nested_within_while_expr() { fn nested_within_while_expr() {
@ -211,7 +214,8 @@ fn nested_within_while_expr() {
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR mismatched types //~| ERROR mismatched types
while let true = let true = true {} //~ ERROR `let` expressions are not supported here while let true = let true = true {}
//~^ ERROR `let` expressions are not supported here
} }
fn not_error_because_clarified_intent() { fn not_error_because_clarified_intent() {
@ -225,45 +229,85 @@ fn not_error_because_clarified_intent() {
} }
fn outside_if_and_while_expr() { fn outside_if_and_while_expr() {
&let 0 = 0; //~ ERROR `let` expressions are not supported here &let 0 = 0;
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
!let 0 = 0; //~ ERROR `let` expressions are not supported here !let 0 = 0;
*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
-let 0 = 0; //~ ERROR `let` expressions are not supported here *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
-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<(), ()> {
let 0 = 0?; 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(())
} }
(let 0 = 0)?; //~ ERROR `let` expressions are not supported here (let 0 = 0)?;
//~^ ERROR the `?` operator can only be used in a function that returns `Result` //~^ ERROR `let` expressions are not supported here
//~| ERROR the `?` operator can only be used in a function that returns `Result`
//~| ERROR the `?` operator can only be applied to values that implement `Try` //~| ERROR the `?` operator can only be applied to values that implement `Try`
//~| ERROR expected expression, found `let` statement
true || let 0 = 0; //~ ERROR `let` expressions are not supported here true || let 0 = 0;
(true || let 0 = 0); //~ ERROR `let` expressions are not supported here //~^ ERROR `let` expressions are not supported here
true && (true || let 0 = 0); //~ ERROR `let` expressions are not supported here //~| ERROR expected expression, found `let` statement
(true || let 0 = 0);
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
true && (true || let 0 = 0);
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
let mut x = true; let mut x = true;
x = let 0 = 0; //~ ERROR `let` expressions are not supported here x = let 0 = 0;
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
true..(let 0 = 0); //~ ERROR `let` expressions are not supported here true..(let 0 = 0);
..(let 0 = 0); //~ ERROR `let` expressions are not supported here //~^ ERROR `let` expressions are not supported here
(let 0 = 0)..; //~ ERROR `let` expressions are not supported here //~| ERROR expected expression, found `let` statement
..(let 0 = 0);
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
(let 0 = 0)..;
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
(let Range { start: _, end: _ } = true..true || false); (let Range { start: _, end: _ } = true..true || false);
//~^ ERROR `let` expressions are not supported here //~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
(let true = let true = true); (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
//~| 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. // Check function tail position.
&let 0 = 0 &let 0 = 0
//~^ ERROR `let` expressions are not supported here //~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
} }
// Let's make sure that `let` inside const generic arguments are considered. // Let's make sure that `let` inside const generic arguments are considered.
@ -335,4 +379,14 @@ fn with_parenthesis() {
let fun = || true; let fun = || true;
if let true = (true && fun()) && (true) { if let true = (true && fun()) && (true) {
} }
#[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
}
} }

View file

@ -17,6 +17,7 @@ fn main() {
//~| ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
return; return;
}; };

View file

@ -9,6 +9,12 @@ help: wrap the expression in parentheses
LL | let Some(n) = (opt && n == 1) else { LL | let Some(n) = (opt && n == 1) else {
| + + | + +
error: expected expression, found `let` statement
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26
|
LL | let Some(n) = opt && let another = n else {
| ^^^
error: a `&&` expression cannot be directly assigned in `let...else` error: a `&&` expression cannot be directly assigned in `let...else`
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
| |
@ -21,43 +27,43 @@ LL | let Some(n) = (opt && let another = n) else {
| + + | + +
error: this `if` expression is missing a block after the condition error: this `if` expression is missing a block after the condition
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:5
| |
LL | if let Some(n) = opt else { LL | if let Some(n) = opt else {
| ^^ | ^^
| |
help: add a block here help: add a block here
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:25
| |
LL | if let Some(n) = opt else { LL | if let Some(n) = opt else {
| ^ | ^
error: this `if` expression is missing a block after the condition error: this `if` expression is missing a block after the condition
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5
| |
LL | if let Some(n) = opt && n == 1 else { LL | if let Some(n) = opt && n == 1 else {
| ^^ | ^^
| |
help: add a block here help: add a block here
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:35
| |
LL | if let Some(n) = opt && n == 1 else { LL | if let Some(n) = opt && n == 1 else {
| ^ | ^
error: this `if` expression is missing a block after the condition error: this `if` expression is missing a block after the condition
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:5
| |
LL | if let Some(n) = opt && let another = n else { LL | if let Some(n) = opt && let another = n else {
| ^^ | ^^
| |
help: add a block here help: add a block here
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:44
| |
LL | if let Some(n) = opt && let another = n else { LL | if let Some(n) = opt && let another = n else {
| ^ | ^
error: expected `{`, found keyword `else` error: expected `{`, found keyword `else`
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:38:33
| |
LL | while let Some(n) = opt else { LL | while let Some(n) = opt else {
| ----- ----------------- ^^^^ expected `{` | ----- ----------------- ^^^^ expected `{`
@ -66,7 +72,7 @@ LL | while let Some(n) = opt else {
| while parsing the body of this `while` expression | while parsing the body of this `while` expression
error: expected `{`, found keyword `else` error: expected `{`, found keyword `else`
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:43:43 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:44:43
| |
LL | while let Some(n) = opt && n == 1 else { LL | while let Some(n) = opt && n == 1 else {
| ----- --------------------------- ^^^^ expected `{` | ----- --------------------------- ^^^^ expected `{`
@ -75,7 +81,7 @@ LL | while let Some(n) = opt && n == 1 else {
| while parsing the body of this `while` expression | while parsing the body of this `while` expression
error: expected `{`, found keyword `else` error: expected `{`, found keyword `else`
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:49:52 --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:50:52
| |
LL | while let Some(n) = opt && let another = n else { LL | while let Some(n) = opt && let another = n else {
| ----- ------------------------------------ ^^^^ expected `{` | ----- ------------------------------------ ^^^^ expected `{`
@ -131,6 +137,6 @@ LL | let Some(n) = opt && let another = n else {
= note: expected type `bool` = note: expected type `bool`
found enum `Option<_>` found enum `Option<_>`
error: aborting due to 13 previous errors error: aborting due to 14 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.

View file

@ -39,6 +39,7 @@ fn _macros() {
noop_expr!((let 0 = 1)); noop_expr!((let 0 = 1));
//~^ ERROR `let` expressions in this position are unstable [E0658] //~^ ERROR `let` expressions in this position are unstable [E0658]
//~| ERROR expected expression, found `let` statement
macro_rules! use_expr { macro_rules! use_expr {
($e:expr) => { ($e:expr) => {
@ -48,9 +49,9 @@ fn _macros() {
} }
#[cfg(FALSE)] (let 0 = 1); #[cfg(FALSE)] (let 0 = 1);
//~^ ERROR `let` expressions in this position are unstable [E0658] //~^ ERROR `let` expressions in this position are unstable [E0658]
//~| ERROR expected expression, found `let` statement
use_expr!(let 0 = 1); use_expr!(let 0 = 1);
//~^ ERROR no rules expected the token `let` //~^ ERROR no rules expected the token `let`
// ^--- FIXME(53667): Consider whether `Let` can be added to `ident_can_begin_expr`.
} }
fn main() {} fn main() {}

View file

@ -1,5 +1,17 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:50:20
|
LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:40:17
|
LL | noop_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let` error: no rules expected the token `let`
--> $DIR/feature-gate.rs:51:15 --> $DIR/feature-gate.rs:53:15
| |
LL | macro_rules! use_expr { LL | macro_rules! use_expr {
| --------------------- when calling this macro | --------------------- when calling this macro
@ -62,7 +74,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:49:20 --> $DIR/feature-gate.rs:50:20
| |
LL | #[cfg(FALSE)] (let 0 = 1); LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^^^^^^^ | ^^^^^^^^^
@ -79,6 +91,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 9 previous errors error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,17 @@
// check-pass
// known-bug
#![feature(let_chains)]
fn main() {
let _opt = Some(1i32);
#[cfg(FALSE)]
{
if let Some(elem) = _opt && {
[1, 2, 3][let _ = ()];
true
} {
}
}
}