[rustc_parse] Forbid lets in certain places
This commit is contained in:
parent
e02d645110
commit
747586732b
13 changed files with 468 additions and 196 deletions
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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 => {}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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
|
||||||
|
} {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue