Auto merge of #115677 - matthewjasper:let-expr-recovery, r=b-naber
Improve invalid let expression handling - Move all of the checks for valid let expression positions to parsing. - Add a field to ExprKind::Let in AST/HIR to mark whether it's in a valid location. - Suppress some later errors and MIR construction for invalid let expressions. - Fix a (drop) scope issue that was also responsible for #104172. Fixes #104172 Fixes #104868
This commit is contained in:
commit
dac91a82e1
48 changed files with 2475 additions and 2287 deletions
|
@ -33,7 +33,7 @@ use rustc_macros::HashStable_Generic;
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
use rustc_span::source_map::{respan, Spanned};
|
use rustc_span::source_map::{respan, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
use thin_vec::{thin_vec, ThinVec};
|
||||||
|
@ -1426,7 +1426,7 @@ pub enum ExprKind {
|
||||||
/// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).
|
/// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).
|
||||||
///
|
///
|
||||||
/// `Span` represents the whole `let pat = expr` statement.
|
/// `Span` represents the whole `let pat = expr` statement.
|
||||||
Let(P<Pat>, P<Expr>, Span),
|
Let(P<Pat>, P<Expr>, Span, Option<ErrorGuaranteed>),
|
||||||
/// An `if` block, with an optional `else` block.
|
/// An `if` block, with an optional `else` block.
|
||||||
///
|
///
|
||||||
/// `if expr { block } else { expr }`
|
/// `if expr { block } else { expr }`
|
||||||
|
|
|
@ -1366,7 +1366,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
}
|
}
|
||||||
ExprKind::AddrOf(_, _, ohs) => vis.visit_expr(ohs),
|
ExprKind::AddrOf(_, _, ohs) => vis.visit_expr(ohs),
|
||||||
ExprKind::Let(pat, scrutinee, _) => {
|
ExprKind::Let(pat, scrutinee, _, _) => {
|
||||||
vis.visit_pat(pat);
|
vis.visit_pat(pat);
|
||||||
vis.visit_expr(scrutinee);
|
vis.visit_expr(scrutinee);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||||
| AssignOp(_, _, e)
|
| AssignOp(_, _, e)
|
||||||
| Binary(_, _, e)
|
| Binary(_, _, e)
|
||||||
| Break(_, Some(e))
|
| Break(_, Some(e))
|
||||||
| Let(_, e, _)
|
| Let(_, e, _, _)
|
||||||
| Range(_, Some(e), _)
|
| Range(_, Some(e), _)
|
||||||
| Ret(Some(e))
|
| Ret(Some(e))
|
||||||
| Unary(_, e)
|
| Unary(_, e)
|
||||||
|
|
|
@ -827,7 +827,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_ty(typ)
|
visitor.visit_ty(typ)
|
||||||
}
|
}
|
||||||
ExprKind::Let(pat, expr, _) => {
|
ExprKind::Let(pat, expr, _, _) => {
|
||||||
visitor.visit_pat(pat);
|
visitor.visit_pat(pat);
|
||||||
visitor.visit_expr(expr);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,13 +152,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let ohs = self.lower_expr(ohs);
|
let ohs = self.lower_expr(ohs);
|
||||||
hir::ExprKind::AddrOf(*k, *m, ohs)
|
hir::ExprKind::AddrOf(*k, *m, ohs)
|
||||||
}
|
}
|
||||||
ExprKind::Let(pat, scrutinee, span) => {
|
ExprKind::Let(pat, scrutinee, span, is_recovered) => {
|
||||||
hir::ExprKind::Let(self.arena.alloc(hir::Let {
|
hir::ExprKind::Let(self.arena.alloc(hir::Let {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
span: self.lower_span(*span),
|
span: self.lower_span(*span),
|
||||||
pat: self.lower_pat(pat),
|
pat: self.lower_pat(pat),
|
||||||
ty: None,
|
ty: None,
|
||||||
init: self.lower_expr(scrutinee),
|
init: self.lower_expr(scrutinee),
|
||||||
|
is_recovered: *is_recovered,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
ExprKind::If(cond, then, else_opt) => {
|
ExprKind::If(cond, then, else_opt) => {
|
||||||
|
@ -558,13 +559,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||||
let pat = self.lower_pat(&arm.pat);
|
let pat = self.lower_pat(&arm.pat);
|
||||||
let guard = arm.guard.as_ref().map(|cond| {
|
let guard = arm.guard.as_ref().map(|cond| {
|
||||||
if let ExprKind::Let(pat, scrutinee, span) = &cond.kind {
|
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
|
||||||
hir::Guard::IfLet(self.arena.alloc(hir::Let {
|
hir::Guard::IfLet(self.arena.alloc(hir::Let {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
span: self.lower_span(*span),
|
span: self.lower_span(*span),
|
||||||
pat: self.lower_pat(pat),
|
pat: self.lower_pat(pat),
|
||||||
ty: None,
|
ty: None,
|
||||||
init: self.lower_expr(scrutinee),
|
init: self.lower_expr(scrutinee),
|
||||||
|
is_recovered: *is_recovered,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
hir::Guard::If(self.lower_expr(cond))
|
hir::Guard::If(self.lower_expr(cond))
|
||||||
|
|
|
@ -117,16 +117,6 @@ ast_passes_forbidden_default =
|
||||||
`default` is only allowed on items in trait impls
|
`default` is only allowed on items in trait impls
|
||||||
.label = `default` because of this
|
.label = `default` because of this
|
||||||
|
|
||||||
ast_passes_forbidden_let =
|
|
||||||
`let` expressions are not supported here
|
|
||||||
.note = only supported directly in conditions of `if` and `while` expressions
|
|
||||||
.not_supported_or = `||` operators are not supported in let chain expressions
|
|
||||||
.not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
|
|
||||||
ast_passes_forbidden_let_stable =
|
|
||||||
expected expression, found statement (`let`)
|
|
||||||
.note = variable declaration using `let` is a statement
|
|
||||||
|
|
||||||
ast_passes_forbidden_lifetime_bound =
|
ast_passes_forbidden_lifetime_bound =
|
||||||
lifetime bounds cannot be used in this context
|
lifetime bounds cannot be used in this context
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,12 @@ use rustc_ast::{walk_list, StaticItem};
|
||||||
use rustc_ast_pretty::pprust::{self, State};
|
use rustc_ast_pretty::pprust::{self, State};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
use rustc_macros::Subdiagnostic;
|
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_session::lint::builtin::{
|
use rustc_session::lint::builtin::{
|
||||||
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
};
|
};
|
||||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::source_map::Spanned;
|
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
@ -69,9 +67,6 @@ struct AstValidator<'a> {
|
||||||
/// or `Foo::Bar<impl Trait>`
|
/// or `Foo::Bar<impl Trait>`
|
||||||
is_impl_trait_banned: bool,
|
is_impl_trait_banned: bool,
|
||||||
|
|
||||||
/// See [ForbiddenLetReason]
|
|
||||||
forbidden_let_reason: Option<ForbiddenLetReason>,
|
|
||||||
|
|
||||||
lint_buffer: &'a mut LintBuffer,
|
lint_buffer: &'a mut LintBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,26 +113,6 @@ impl<'a> AstValidator<'a> {
|
||||||
self.with_tilde_const(Some(ctx), f)
|
self.with_tilde_const(Some(ctx), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_let_management(
|
|
||||||
&mut self,
|
|
||||||
forbidden_let_reason: Option<ForbiddenLetReason>,
|
|
||||||
f: impl FnOnce(&mut Self, Option<ForbiddenLetReason>),
|
|
||||||
) {
|
|
||||||
let old = mem::replace(&mut self.forbidden_let_reason, forbidden_let_reason);
|
|
||||||
f(self, old);
|
|
||||||
self.forbidden_let_reason = old;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emits an error banning the `let` expression provided in the given location.
|
|
||||||
fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
|
|
||||||
let sess = &self.session;
|
|
||||||
if sess.opts.unstable_features.is_nightly_build() {
|
|
||||||
sess.emit_err(errors::ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
|
|
||||||
} else {
|
|
||||||
sess.emit_err(errors::ForbiddenLetStable { span: expr.span });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_type_alias_where_clause_location(
|
fn check_type_alias_where_clause_location(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty_alias: &TyAlias,
|
ty_alias: &TyAlias,
|
||||||
|
@ -779,67 +754,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
validate_attr::check_attr(&self.session.parse_sess, attr);
|
validate_attr::check_attr(&self.session.parse_sess, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
|
||||||
self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| {
|
|
||||||
match &expr.kind {
|
|
||||||
ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => {
|
|
||||||
let local_reason = Some(ForbiddenLetReason::NotSupportedOr(*span));
|
|
||||||
this.with_let_management(local_reason, |this, _| this.visit_expr(lhs));
|
|
||||||
this.with_let_management(local_reason, |this, _| this.visit_expr(rhs));
|
|
||||||
}
|
|
||||||
ExprKind::If(cond, then, opt_else) => {
|
|
||||||
this.visit_block(then);
|
|
||||||
walk_list!(this, visit_expr, opt_else);
|
|
||||||
this.with_let_management(None, |this, _| this.visit_expr(cond));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ExprKind::Let(..) if let Some(elem) = forbidden_let_reason => {
|
|
||||||
this.ban_let_expr(expr, elem);
|
|
||||||
},
|
|
||||||
ExprKind::Match(scrutinee, arms) => {
|
|
||||||
this.visit_expr(scrutinee);
|
|
||||||
for arm in arms {
|
|
||||||
this.visit_expr(&arm.body);
|
|
||||||
this.visit_pat(&arm.pat);
|
|
||||||
walk_list!(this, visit_attribute, &arm.attrs);
|
|
||||||
if let Some(guard) = &arm.guard {
|
|
||||||
this.with_let_management(None, |this, _| {
|
|
||||||
this.visit_expr(guard)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Paren(local_expr) => {
|
|
||||||
fn has_let_expr(expr: &Expr) -> bool {
|
|
||||||
match &expr.kind {
|
|
||||||
ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
|
|
||||||
ExprKind::Let(..) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let local_reason = if has_let_expr(local_expr) {
|
|
||||||
Some(ForbiddenLetReason::NotSupportedParentheses(local_expr.span))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
forbidden_let_reason
|
|
||||||
};
|
|
||||||
this.with_let_management(local_reason, |this, _| this.visit_expr(local_expr));
|
|
||||||
}
|
|
||||||
ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
|
|
||||||
this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ExprKind::While(cond, then, opt_label) => {
|
|
||||||
walk_list!(this, visit_label, opt_label);
|
|
||||||
this.visit_block(then);
|
|
||||||
this.with_let_management(None, |this, _| this.visit_expr(cond));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ => visit::walk_expr(this, expr),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||||
self.visit_ty_common(ty);
|
self.visit_ty_common(ty);
|
||||||
self.deny_anon_struct_or_union(ty);
|
self.deny_anon_struct_or_union(ty);
|
||||||
|
@ -1601,26 +1515,9 @@ pub fn check_crate(
|
||||||
outer_impl_trait: None,
|
outer_impl_trait: None,
|
||||||
disallow_tilde_const: None,
|
disallow_tilde_const: None,
|
||||||
is_impl_trait_banned: false,
|
is_impl_trait_banned: false,
|
||||||
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
|
|
||||||
lint_buffer: lints,
|
lint_buffer: lints,
|
||||||
};
|
};
|
||||||
visit::walk_crate(&mut validator, krate);
|
visit::walk_crate(&mut validator, krate);
|
||||||
|
|
||||||
validator.has_proc_macro_decls
|
validator.has_proc_macro_decls
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to forbid `let` expressions in certain syntactic locations.
|
|
||||||
#[derive(Clone, Copy, Subdiagnostic)]
|
|
||||||
pub(crate) enum ForbiddenLetReason {
|
|
||||||
/// `let` is not valid and the source environment is not important
|
|
||||||
GenericForbidden,
|
|
||||||
/// A let chain with the `||` operator
|
|
||||||
#[note(ast_passes_not_supported_or)]
|
|
||||||
NotSupportedOr(#[primary_span] Span),
|
|
||||||
/// A let chain with invalid parentheses
|
|
||||||
///
|
|
||||||
/// For example, `let 1 = 1 && (expr && expr)` is allowed
|
|
||||||
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
|
|
||||||
#[note(ast_passes_not_supported_parentheses)]
|
|
||||||
NotSupportedParentheses(#[primary_span] Span),
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,27 +5,8 @@ use rustc_errors::AddToDiagnostic;
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
use crate::ast_validation::ForbiddenLetReason;
|
|
||||||
use crate::fluent_generated as fluent;
|
use crate::fluent_generated as fluent;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(ast_passes_forbidden_let)]
|
|
||||||
#[note]
|
|
||||||
pub struct ForbiddenLet {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
#[subdiagnostic]
|
|
||||||
pub(crate) reason: ForbiddenLetReason,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(ast_passes_forbidden_let_stable)]
|
|
||||||
#[note]
|
|
||||||
pub struct ForbiddenLetStable {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_keyword_lifetime)]
|
#[diag(ast_passes_keyword_lifetime)]
|
||||||
pub struct KeywordLifetime {
|
pub struct KeywordLifetime {
|
||||||
|
|
|
@ -352,7 +352,7 @@ impl<'a> State<'a> {
|
||||||
self.end();
|
self.end();
|
||||||
self.word(")");
|
self.word(")");
|
||||||
}
|
}
|
||||||
ast::ExprKind::Let(pat, scrutinee, _) => {
|
ast::ExprKind::Let(pat, scrutinee, _, _) => {
|
||||||
self.print_let(pat, scrutinee);
|
self.print_let(pat, scrutinee);
|
||||||
}
|
}
|
||||||
ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
|
ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
|
||||||
|
|
|
@ -241,7 +241,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||||
self.manage_cond_expr(prefix);
|
self.manage_cond_expr(prefix);
|
||||||
self.manage_cond_expr(suffix);
|
self.manage_cond_expr(suffix);
|
||||||
}
|
}
|
||||||
ExprKind::Let(_, local_expr, _) => {
|
ExprKind::Let(_, local_expr, _, _) => {
|
||||||
self.manage_cond_expr(local_expr);
|
self.manage_cond_expr(local_expr);
|
||||||
}
|
}
|
||||||
ExprKind::Match(local_expr, _) => {
|
ExprKind::Match(local_expr, _) => {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use rustc_macros::HashStable_Generic;
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::MacroKind;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
|
use rustc_span::ErrorGuaranteed;
|
||||||
use rustc_span::{def_id::LocalDefId, BytePos, Span, DUMMY_SP};
|
use rustc_span::{def_id::LocalDefId, BytePos, Span, DUMMY_SP};
|
||||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
@ -1415,6 +1416,9 @@ pub struct Let<'hir> {
|
||||||
pub pat: &'hir Pat<'hir>,
|
pub pat: &'hir Pat<'hir>,
|
||||||
pub ty: Option<&'hir Ty<'hir>>,
|
pub ty: Option<&'hir Ty<'hir>>,
|
||||||
pub init: &'hir Expr<'hir>,
|
pub init: &'hir Expr<'hir>,
|
||||||
|
/// `Some` when this let expressions is not in a syntanctically valid location.
|
||||||
|
/// Used to prevent building MIR in such situations.
|
||||||
|
pub is_recovered: Option<ErrorGuaranteed>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
|
|
|
@ -149,7 +149,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
|
||||||
// From now on, we continue normally.
|
// From now on, we continue normally.
|
||||||
visitor.cx = prev_cx;
|
visitor.cx = prev_cx;
|
||||||
}
|
}
|
||||||
hir::StmtKind::Local(..) | hir::StmtKind::Item(..) => {
|
hir::StmtKind::Local(..) => {
|
||||||
// Each declaration introduces a subscope for bindings
|
// Each declaration introduces a subscope for bindings
|
||||||
// introduced by the declaration; this subscope covers a
|
// introduced by the declaration; this subscope covers a
|
||||||
// suffix of the block. Each subscope in a block has the
|
// suffix of the block. Each subscope in a block has the
|
||||||
|
@ -163,6 +163,10 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
|
||||||
visitor.cx.var_parent = visitor.cx.parent;
|
visitor.cx.var_parent = visitor.cx.parent;
|
||||||
visitor.visit_stmt(statement)
|
visitor.visit_stmt(statement)
|
||||||
}
|
}
|
||||||
|
hir::StmtKind::Item(..) => {
|
||||||
|
// Don't create scopes for items, since they won't be
|
||||||
|
// lowered to THIR and MIR.
|
||||||
|
}
|
||||||
hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => visitor.visit_stmt(statement),
|
hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => visitor.visit_stmt(statement),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1203,7 +1203,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// otherwise check exactly as a let statement
|
// otherwise check exactly as a let statement
|
||||||
self.check_decl(let_expr.into());
|
self.check_decl(let_expr.into());
|
||||||
// but return a bool, for this is a boolean expression
|
// but return a bool, for this is a boolean expression
|
||||||
self.tcx.types.bool
|
if let Some(error_guaranteed) = let_expr.is_recovered {
|
||||||
|
self.set_tainted_by_errors(error_guaranteed);
|
||||||
|
Ty::new_error(self.tcx, error_guaranteed)
|
||||||
|
} else {
|
||||||
|
self.tcx.types.bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_loop(
|
fn check_expr_loop(
|
||||||
|
|
|
@ -50,7 +50,7 @@ impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
|
||||||
|
|
||||||
impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
|
impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
|
||||||
fn from(let_expr: &'a hir::Let<'a>) -> Self {
|
fn from(let_expr: &'a hir::Let<'a>) -> Self {
|
||||||
let hir::Let { hir_id, pat, ty, span, init } = *let_expr;
|
let hir::Let { hir_id, pat, ty, span, init, is_recovered: _ } = *let_expr;
|
||||||
Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
|
Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -816,8 +816,7 @@ trait UnusedDelimLint {
|
||||||
let (value, ctx, followed_by_block, left_pos, right_pos, is_kw) = match e.kind {
|
let (value, ctx, followed_by_block, left_pos, right_pos, is_kw) = match e.kind {
|
||||||
// Do not lint `unused_braces` in `if let` expressions.
|
// Do not lint `unused_braces` in `if let` expressions.
|
||||||
If(ref cond, ref block, _)
|
If(ref cond, ref block, _)
|
||||||
if !matches!(cond.kind, Let(_, _, _))
|
if !matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
|
||||||
|| Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
|
|
||||||
{
|
{
|
||||||
let left = e.span.lo() + rustc_span::BytePos(2);
|
let left = e.span.lo() + rustc_span::BytePos(2);
|
||||||
let right = block.span.lo();
|
let right = block.span.lo();
|
||||||
|
@ -826,8 +825,7 @@ trait UnusedDelimLint {
|
||||||
|
|
||||||
// Do not lint `unused_braces` in `while let` expressions.
|
// Do not lint `unused_braces` in `while let` expressions.
|
||||||
While(ref cond, ref block, ..)
|
While(ref cond, ref block, ..)
|
||||||
if !matches!(cond.kind, Let(_, _, _))
|
if !matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
|
||||||
|| Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
|
|
||||||
{
|
{
|
||||||
let left = e.span.lo() + rustc_span::BytePos(5);
|
let left = e.span.lo() + rustc_span::BytePos(5);
|
||||||
let right = block.span.lo();
|
let right = block.span.lo();
|
||||||
|
@ -1003,7 +1001,7 @@ impl UnusedDelimLint for UnusedParens {
|
||||||
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
|
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Let(_, ref expr, _) => {
|
ast::ExprKind::Let(_, ref expr, _, _) => {
|
||||||
self.check_unused_delims_expr(
|
self.check_unused_delims_expr(
|
||||||
cx,
|
cx,
|
||||||
expr,
|
expr,
|
||||||
|
@ -1067,7 +1065,7 @@ impl EarlyLintPass for UnusedParens {
|
||||||
}
|
}
|
||||||
|
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
|
ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop(ref pat, ..) => {
|
||||||
self.check_unused_parens_pat(cx, pat, false, false, (true, true));
|
self.check_unused_parens_pat(cx, pat, false, false, (true, true));
|
||||||
}
|
}
|
||||||
// We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
|
// We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
|
||||||
|
@ -1311,7 +1309,7 @@ impl UnusedDelimLint for UnusedBraces {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Let(_, ref expr, _) => {
|
ast::ExprKind::Let(_, ref expr, _, _) => {
|
||||||
self.check_unused_delims_expr(
|
self.check_unused_delims_expr(
|
||||||
cx,
|
cx,
|
||||||
expr,
|
expr,
|
||||||
|
|
|
@ -196,6 +196,9 @@ parse_expected_else_block = expected `{"{"}`, found {$first_tok}
|
||||||
.suggestion = add an `if` if this is the condition of a chained `else if` statement
|
.suggestion = add an `if` if this is the condition of a chained `else if` statement
|
||||||
|
|
||||||
parse_expected_expression_found_let = expected expression, found `let` statement
|
parse_expected_expression_found_let = expected expression, found `let` statement
|
||||||
|
.note = only supported directly in conditions of `if` and `while` expressions
|
||||||
|
.not_supported_or = `||` operators are not supported in let chain expressions
|
||||||
|
.not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
|
||||||
parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
|
parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
|
||||||
.suggestion = use `Fn` to refer to the trait
|
.suggestion = use `Fn` to refer to the trait
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
use crate::fluent_generated as fluent;
|
use crate::fluent_generated as fluent;
|
||||||
use crate::parser::TokenDescription;
|
use crate::parser::{ForbiddenLetReason, TokenDescription};
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_maybe_report_ambiguous_plus)]
|
#[diag(parse_maybe_report_ambiguous_plus)]
|
||||||
|
@ -392,9 +392,12 @@ pub(crate) struct IfExpressionMissingCondition {
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_expected_expression_found_let)]
|
#[diag(parse_expected_expression_found_let)]
|
||||||
|
#[note]
|
||||||
pub(crate) struct ExpectedExpressionFoundLet {
|
pub(crate) struct ExpectedExpressionFoundLet {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub reason: ForbiddenLetReason,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -8,6 +8,7 @@ use super::{
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||||
|
use ast::mut_visit::{noop_visit_expr, MutVisitor};
|
||||||
use ast::{Path, PathSegment};
|
use ast::{Path, PathSegment};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
|
@ -27,6 +28,7 @@ use rustc_errors::{
|
||||||
AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
||||||
PResult, StashKey,
|
PResult, StashKey,
|
||||||
};
|
};
|
||||||
|
use rustc_macros::Subdiagnostic;
|
||||||
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
|
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
|
||||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||||
|
@ -122,8 +124,8 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
|
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
|
||||||
match self.parse_expr() {
|
match self.parse_expr_res(restrictions, None) {
|
||||||
Ok(expr) => Ok(expr),
|
Ok(expr) => Ok(expr),
|
||||||
Err(mut err) => match self.token.ident() {
|
Err(mut err) => match self.token.ident() {
|
||||||
Some((Ident { name: kw::Underscore, .. }, false))
|
Some((Ident { name: kw::Underscore, .. }, false))
|
||||||
|
@ -141,7 +143,8 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses a sequence of expressions delimited by parentheses.
|
/// Parses a sequence of expressions delimited by parentheses.
|
||||||
fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
|
fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
|
||||||
self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r)
|
self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty()))
|
||||||
|
.map(|(r, _)| r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an expression, subject to the given restrictions.
|
/// Parses an expression, subject to the given restrictions.
|
||||||
|
@ -1345,110 +1348,113 @@ impl<'a> Parser<'a> {
|
||||||
// Outer attributes are already parsed and will be
|
// Outer attributes are already parsed and will be
|
||||||
// added to the return value after the fact.
|
// added to the return value after the fact.
|
||||||
|
|
||||||
// Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
|
let restrictions = self.restrictions;
|
||||||
let lo = self.token.span;
|
self.with_res(restrictions - Restrictions::ALLOW_LET, |this| {
|
||||||
if let token::Literal(_) = self.token.kind {
|
// Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
|
||||||
// This match arm is a special-case of the `_` match arm below and
|
let lo = this.token.span;
|
||||||
// could be removed without changing functionality, but it's faster
|
if let token::Literal(_) = this.token.kind {
|
||||||
// to have it here, especially for programs with large constants.
|
// This match arm is a special-case of the `_` match arm below and
|
||||||
self.parse_expr_lit()
|
// could be removed without changing functionality, but it's faster
|
||||||
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
// to have it here, especially for programs with large constants.
|
||||||
self.parse_expr_tuple_parens()
|
this.parse_expr_lit()
|
||||||
} else if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
} else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||||
self.parse_expr_block(None, lo, BlockCheckMode::Default)
|
this.parse_expr_tuple_parens(restrictions)
|
||||||
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
|
} else if this.check(&token::OpenDelim(Delimiter::Brace)) {
|
||||||
self.parse_expr_closure().map_err(|mut err| {
|
this.parse_expr_block(None, lo, BlockCheckMode::Default)
|
||||||
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
|
} else if this.check(&token::BinOp(token::Or)) || this.check(&token::OrOr) {
|
||||||
// then suggest parens around the lhs.
|
this.parse_expr_closure().map_err(|mut err| {
|
||||||
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
|
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
|
||||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
// then suggest parens around the lhs.
|
||||||
}
|
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
|
||||||
err
|
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||||
})
|
}
|
||||||
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
|
|
||||||
self.parse_expr_array_or_repeat(Delimiter::Bracket)
|
|
||||||
} else if self.is_builtin() {
|
|
||||||
self.parse_expr_builtin()
|
|
||||||
} else if self.check_path() {
|
|
||||||
self.parse_expr_path_start()
|
|
||||||
} else if self.check_keyword(kw::Move)
|
|
||||||
|| self.check_keyword(kw::Static)
|
|
||||||
|| self.check_const_closure()
|
|
||||||
{
|
|
||||||
self.parse_expr_closure()
|
|
||||||
} else if self.eat_keyword(kw::If) {
|
|
||||||
self.parse_expr_if()
|
|
||||||
} else if self.check_keyword(kw::For) {
|
|
||||||
if self.choose_generics_over_qpath(1) {
|
|
||||||
self.parse_expr_closure()
|
|
||||||
} else {
|
|
||||||
assert!(self.eat_keyword(kw::For));
|
|
||||||
self.parse_expr_for(None, self.prev_token.span)
|
|
||||||
}
|
|
||||||
} else if self.eat_keyword(kw::While) {
|
|
||||||
self.parse_expr_while(None, self.prev_token.span)
|
|
||||||
} else if let Some(label) = self.eat_label() {
|
|
||||||
self.parse_expr_labeled(label, true)
|
|
||||||
} else if self.eat_keyword(kw::Loop) {
|
|
||||||
let sp = self.prev_token.span;
|
|
||||||
self.parse_expr_loop(None, self.prev_token.span).map_err(|mut err| {
|
|
||||||
err.span_label(sp, "while parsing this `loop` expression");
|
|
||||||
err
|
|
||||||
})
|
|
||||||
} else if self.eat_keyword(kw::Match) {
|
|
||||||
let match_sp = self.prev_token.span;
|
|
||||||
self.parse_expr_match().map_err(|mut err| {
|
|
||||||
err.span_label(match_sp, "while parsing this `match` expression");
|
|
||||||
err
|
|
||||||
})
|
|
||||||
} else if self.eat_keyword(kw::Unsafe) {
|
|
||||||
let sp = self.prev_token.span;
|
|
||||||
self.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|
|
||||||
|mut err| {
|
|
||||||
err.span_label(sp, "while parsing this `unsafe` expression");
|
|
||||||
err
|
err
|
||||||
},
|
})
|
||||||
)
|
} else if this.check(&token::OpenDelim(Delimiter::Bracket)) {
|
||||||
} else if self.check_inline_const(0) {
|
this.parse_expr_array_or_repeat(Delimiter::Bracket)
|
||||||
self.parse_const_block(lo.to(self.token.span), false)
|
} else if this.is_builtin() {
|
||||||
} else if self.may_recover() && self.is_do_catch_block() {
|
this.parse_expr_builtin()
|
||||||
self.recover_do_catch()
|
} else if this.check_path() {
|
||||||
} else if self.is_try_block() {
|
this.parse_expr_path_start()
|
||||||
self.expect_keyword(kw::Try)?;
|
} else if this.check_keyword(kw::Move)
|
||||||
self.parse_try_block(lo)
|
|| this.check_keyword(kw::Static)
|
||||||
} else if self.eat_keyword(kw::Return) {
|
|| this.check_const_closure()
|
||||||
self.parse_expr_return()
|
{
|
||||||
} else if self.eat_keyword(kw::Continue) {
|
this.parse_expr_closure()
|
||||||
self.parse_expr_continue(lo)
|
} else if this.eat_keyword(kw::If) {
|
||||||
} else if self.eat_keyword(kw::Break) {
|
this.parse_expr_if()
|
||||||
self.parse_expr_break()
|
} else if this.check_keyword(kw::For) {
|
||||||
} else if self.eat_keyword(kw::Yield) {
|
if this.choose_generics_over_qpath(1) {
|
||||||
self.parse_expr_yield()
|
this.parse_expr_closure()
|
||||||
} else if self.is_do_yeet() {
|
|
||||||
self.parse_expr_yeet()
|
|
||||||
} else if self.eat_keyword(kw::Become) {
|
|
||||||
self.parse_expr_become()
|
|
||||||
} else if self.check_keyword(kw::Let) {
|
|
||||||
self.parse_expr_let()
|
|
||||||
} else if self.eat_keyword(kw::Underscore) {
|
|
||||||
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
|
|
||||||
} else if self.token.uninterpolated_span().at_least_rust_2018() {
|
|
||||||
// `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
|
|
||||||
if self.check_keyword(kw::Async) {
|
|
||||||
if self.is_async_block() {
|
|
||||||
// Check for `async {` and `async move {`.
|
|
||||||
self.parse_async_block()
|
|
||||||
} else {
|
} else {
|
||||||
self.parse_expr_closure()
|
assert!(this.eat_keyword(kw::For));
|
||||||
|
this.parse_expr_for(None, this.prev_token.span)
|
||||||
|
}
|
||||||
|
} else if this.eat_keyword(kw::While) {
|
||||||
|
this.parse_expr_while(None, this.prev_token.span)
|
||||||
|
} else if let Some(label) = this.eat_label() {
|
||||||
|
this.parse_expr_labeled(label, true)
|
||||||
|
} else if this.eat_keyword(kw::Loop) {
|
||||||
|
let sp = this.prev_token.span;
|
||||||
|
this.parse_expr_loop(None, this.prev_token.span).map_err(|mut err| {
|
||||||
|
err.span_label(sp, "while parsing this `loop` expression");
|
||||||
|
err
|
||||||
|
})
|
||||||
|
} else if this.eat_keyword(kw::Match) {
|
||||||
|
let match_sp = this.prev_token.span;
|
||||||
|
this.parse_expr_match().map_err(|mut err| {
|
||||||
|
err.span_label(match_sp, "while parsing this `match` expression");
|
||||||
|
err
|
||||||
|
})
|
||||||
|
} else if this.eat_keyword(kw::Unsafe) {
|
||||||
|
let sp = this.prev_token.span;
|
||||||
|
this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|
||||||
|
|mut err| {
|
||||||
|
err.span_label(sp, "while parsing this `unsafe` expression");
|
||||||
|
err
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else if this.check_inline_const(0) {
|
||||||
|
this.parse_const_block(lo.to(this.token.span), false)
|
||||||
|
} else if this.may_recover() && this.is_do_catch_block() {
|
||||||
|
this.recover_do_catch()
|
||||||
|
} else if this.is_try_block() {
|
||||||
|
this.expect_keyword(kw::Try)?;
|
||||||
|
this.parse_try_block(lo)
|
||||||
|
} else if this.eat_keyword(kw::Return) {
|
||||||
|
this.parse_expr_return()
|
||||||
|
} else if this.eat_keyword(kw::Continue) {
|
||||||
|
this.parse_expr_continue(lo)
|
||||||
|
} else if this.eat_keyword(kw::Break) {
|
||||||
|
this.parse_expr_break()
|
||||||
|
} else if this.eat_keyword(kw::Yield) {
|
||||||
|
this.parse_expr_yield()
|
||||||
|
} else if this.is_do_yeet() {
|
||||||
|
this.parse_expr_yeet()
|
||||||
|
} else if this.eat_keyword(kw::Become) {
|
||||||
|
this.parse_expr_become()
|
||||||
|
} else if this.check_keyword(kw::Let) {
|
||||||
|
this.parse_expr_let(restrictions)
|
||||||
|
} else if this.eat_keyword(kw::Underscore) {
|
||||||
|
Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
|
||||||
|
} else if this.token.uninterpolated_span().at_least_rust_2018() {
|
||||||
|
// `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||||
|
if this.check_keyword(kw::Async) {
|
||||||
|
if this.is_async_block() {
|
||||||
|
// Check for `async {` and `async move {`.
|
||||||
|
this.parse_async_block()
|
||||||
|
} else {
|
||||||
|
this.parse_expr_closure()
|
||||||
|
}
|
||||||
|
} else if this.eat_keyword(kw::Await) {
|
||||||
|
this.recover_incorrect_await_syntax(lo, this.prev_token.span)
|
||||||
|
} else {
|
||||||
|
this.parse_expr_lit()
|
||||||
}
|
}
|
||||||
} else if self.eat_keyword(kw::Await) {
|
|
||||||
self.recover_incorrect_await_syntax(lo, self.prev_token.span)
|
|
||||||
} else {
|
} else {
|
||||||
self.parse_expr_lit()
|
this.parse_expr_lit()
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
self.parse_expr_lit()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
|
@ -1462,13 +1468,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr_tuple_parens(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||||
let (es, trailing_comma) = match self.parse_seq_to_end(
|
let (es, trailing_comma) = match self.parse_seq_to_end(
|
||||||
&token::CloseDelim(Delimiter::Parenthesis),
|
&token::CloseDelim(Delimiter::Parenthesis),
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|p| p.parse_expr_catch_underscore(),
|
|p| p.parse_expr_catch_underscore(restrictions.intersection(Restrictions::ALLOW_LET)),
|
||||||
) {
|
) {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -2231,7 +2237,8 @@ impl<'a> Parser<'a> {
|
||||||
let decl_hi = self.prev_token.span;
|
let decl_hi = self.prev_token.span;
|
||||||
let mut body = match fn_decl.output {
|
let mut body = match fn_decl.output {
|
||||||
FnRetTy::Default(_) => {
|
FnRetTy::Default(_) => {
|
||||||
let restrictions = self.restrictions - Restrictions::STMT_EXPR;
|
let restrictions =
|
||||||
|
self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
|
||||||
self.parse_expr_res(restrictions, None)?
|
self.parse_expr_res(restrictions, None)?
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -2436,10 +2443,12 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses the condition of a `if` or `while` expression.
|
/// Parses the condition of a `if` or `while` expression.
|
||||||
fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
let cond =
|
let mut cond =
|
||||||
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
|
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
|
||||||
|
|
||||||
if let ExprKind::Let(..) = cond.kind {
|
CondChecker { parser: self, forbid_let_reason: None }.visit_expr(&mut cond);
|
||||||
|
|
||||||
|
if let ExprKind::Let(_, _, _, None) = 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.
|
||||||
self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
|
self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
|
||||||
}
|
}
|
||||||
|
@ -2448,18 +2457,15 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a `let $pat = $expr` pseudo-expression.
|
/// Parses a `let $pat = $expr` pseudo-expression.
|
||||||
fn parse_expr_let(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
|
||||||
// This is a *approximate* heuristic that detects if `let` chains are
|
let is_recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
|
||||||
// being parsed in the right position. It's approximate because it
|
Some(self.sess.emit_err(errors::ExpectedExpressionFoundLet {
|
||||||
// doesn't deny all invalid `let` expressions, just completely wrong usages.
|
span: self.token.span,
|
||||||
let not_in_chain = !matches!(
|
reason: ForbiddenLetReason::OtherForbidden,
|
||||||
self.prev_token.kind,
|
}))
|
||||||
TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
|
} else {
|
||||||
);
|
None
|
||||||
if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
|
};
|
||||||
self.sess.emit_err(errors::ExpectedExpressionFoundLet { span: self.token.span });
|
|
||||||
}
|
|
||||||
|
|
||||||
self.bump(); // Eat `let` token
|
self.bump(); // Eat `let` token
|
||||||
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(
|
||||||
|
@ -2479,8 +2485,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())?;
|
let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())?;
|
||||||
let span = lo.to(expr.span);
|
let span = lo.to(expr.span);
|
||||||
self.sess.gated_spans.gate(sym::let_chains, span);
|
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, is_recovered)))
|
||||||
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an `else { ... }` expression (`else` token already eaten).
|
/// Parses an `else { ... }` expression (`else` token already eaten).
|
||||||
|
@ -2829,7 +2834,10 @@ 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_res(Restrictions::ALLOW_LET, None)?;
|
let mut cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?;
|
||||||
|
|
||||||
|
CondChecker { parser: this, forbid_let_reason: None }.visit_expr(&mut cond);
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -3414,3 +3422,130 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used to forbid `let` expressions in certain syntactic locations.
|
||||||
|
#[derive(Clone, Copy, Subdiagnostic)]
|
||||||
|
pub(crate) enum ForbiddenLetReason {
|
||||||
|
/// `let` is not valid and the source environment is not important
|
||||||
|
OtherForbidden,
|
||||||
|
/// A let chain with the `||` operator
|
||||||
|
#[note(parse_not_supported_or)]
|
||||||
|
NotSupportedOr(#[primary_span] Span),
|
||||||
|
/// A let chain with invalid parentheses
|
||||||
|
///
|
||||||
|
/// For example, `let 1 = 1 && (expr && expr)` is allowed
|
||||||
|
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
|
||||||
|
#[note(parse_not_supported_parentheses)]
|
||||||
|
NotSupportedParentheses(#[primary_span] Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Visitor to check for invalid/unstable use of `ExprKind::Let` that can't
|
||||||
|
/// easily be caught in parsing. For example:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore (example)
|
||||||
|
/// // Only know that the let isn't allowed once the `||` token is reached
|
||||||
|
/// if let Some(x) = y || true {}
|
||||||
|
/// // Only know that the let isn't allowed once the second `=` token is reached.
|
||||||
|
/// if let Some(x) = y && z = 1 {}
|
||||||
|
/// ```
|
||||||
|
struct CondChecker<'a> {
|
||||||
|
parser: &'a Parser<'a>,
|
||||||
|
forbid_let_reason: Option<ForbiddenLetReason>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MutVisitor for CondChecker<'_> {
|
||||||
|
fn visit_expr(&mut self, e: &mut P<Expr>) {
|
||||||
|
use ForbiddenLetReason::*;
|
||||||
|
|
||||||
|
let span = e.span;
|
||||||
|
match e.kind {
|
||||||
|
ExprKind::Let(_, _, _, ref mut is_recovered @ None) => {
|
||||||
|
if let Some(reason) = self.forbid_let_reason {
|
||||||
|
*is_recovered = Some(
|
||||||
|
self.parser
|
||||||
|
.sess
|
||||||
|
.emit_err(errors::ExpectedExpressionFoundLet { span, reason }),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.parser.sess.gated_spans.gate(sym::let_chains, span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
|
||||||
|
noop_visit_expr(e, self);
|
||||||
|
}
|
||||||
|
ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _)
|
||||||
|
if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason =>
|
||||||
|
{
|
||||||
|
let forbid_let_reason = self.forbid_let_reason;
|
||||||
|
self.forbid_let_reason = Some(NotSupportedOr(or_span));
|
||||||
|
noop_visit_expr(e, self);
|
||||||
|
self.forbid_let_reason = forbid_let_reason;
|
||||||
|
}
|
||||||
|
ExprKind::Paren(ref inner)
|
||||||
|
if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason =>
|
||||||
|
{
|
||||||
|
let forbid_let_reason = self.forbid_let_reason;
|
||||||
|
self.forbid_let_reason = Some(NotSupportedParentheses(inner.span));
|
||||||
|
noop_visit_expr(e, self);
|
||||||
|
self.forbid_let_reason = forbid_let_reason;
|
||||||
|
}
|
||||||
|
ExprKind::Unary(_, _)
|
||||||
|
| ExprKind::Await(_, _)
|
||||||
|
| ExprKind::Assign(_, _, _)
|
||||||
|
| ExprKind::AssignOp(_, _, _)
|
||||||
|
| ExprKind::Range(_, _, _)
|
||||||
|
| ExprKind::Try(_)
|
||||||
|
| ExprKind::AddrOf(_, _, _)
|
||||||
|
| ExprKind::Binary(_, _, _)
|
||||||
|
| ExprKind::Field(_, _)
|
||||||
|
| ExprKind::Index(_, _, _)
|
||||||
|
| ExprKind::Call(_, _)
|
||||||
|
| ExprKind::MethodCall(_)
|
||||||
|
| ExprKind::Tup(_)
|
||||||
|
| ExprKind::Paren(_) => {
|
||||||
|
let forbid_let_reason = self.forbid_let_reason;
|
||||||
|
self.forbid_let_reason = Some(OtherForbidden);
|
||||||
|
noop_visit_expr(e, self);
|
||||||
|
self.forbid_let_reason = forbid_let_reason;
|
||||||
|
}
|
||||||
|
ExprKind::Cast(ref mut op, _)
|
||||||
|
| ExprKind::Type(ref mut op, _) => {
|
||||||
|
let forbid_let_reason = self.forbid_let_reason;
|
||||||
|
self.forbid_let_reason = Some(OtherForbidden);
|
||||||
|
self.visit_expr(op);
|
||||||
|
self.forbid_let_reason = forbid_let_reason;
|
||||||
|
}
|
||||||
|
ExprKind::Let(_, _, _, Some(_))
|
||||||
|
| ExprKind::Array(_)
|
||||||
|
| ExprKind::ConstBlock(_)
|
||||||
|
| ExprKind::Lit(_)
|
||||||
|
| ExprKind::If(_, _, _)
|
||||||
|
| ExprKind::While(_, _, _)
|
||||||
|
| ExprKind::ForLoop(_, _, _, _)
|
||||||
|
| ExprKind::Loop(_, _, _)
|
||||||
|
| ExprKind::Match(_, _)
|
||||||
|
| ExprKind::Closure(_)
|
||||||
|
| ExprKind::Block(_, _)
|
||||||
|
| ExprKind::Async(_, _)
|
||||||
|
| ExprKind::TryBlock(_)
|
||||||
|
| ExprKind::Underscore
|
||||||
|
| ExprKind::Path(_, _)
|
||||||
|
| ExprKind::Break(_, _)
|
||||||
|
| ExprKind::Continue(_)
|
||||||
|
| ExprKind::Ret(_)
|
||||||
|
| ExprKind::InlineAsm(_)
|
||||||
|
| ExprKind::OffsetOf(_, _)
|
||||||
|
| ExprKind::MacCall(_)
|
||||||
|
| ExprKind::Struct(_)
|
||||||
|
| ExprKind::Repeat(_, _)
|
||||||
|
| ExprKind::Yield(_)
|
||||||
|
| ExprKind::Yeet(_)
|
||||||
|
| ExprKind::Become(_)
|
||||||
|
| ExprKind::IncludedBytes(_)
|
||||||
|
| ExprKind::FormatArgs(_)
|
||||||
|
| ExprKind::Err => {
|
||||||
|
// These would forbid any let expressions they contain already.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod ty;
|
||||||
use crate::lexer::UnmatchedDelim;
|
use crate::lexer::UnmatchedDelim;
|
||||||
pub use attr_wrapper::AttrWrapper;
|
pub use attr_wrapper::AttrWrapper;
|
||||||
pub use diagnostics::AttemptLocalParseRecovery;
|
pub use diagnostics::AttemptLocalParseRecovery;
|
||||||
|
pub(crate) use expr::ForbiddenLetReason;
|
||||||
pub(crate) use item::FnParseMode;
|
pub(crate) use item::FnParseMode;
|
||||||
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
||||||
pub use path::PathStyle;
|
pub use path::PathStyle;
|
||||||
|
|
|
@ -4180,7 +4180,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
self.resolve_expr(e, Some(&expr));
|
self.resolve_expr(e, Some(&expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Let(ref pat, ref scrutinee, _) => {
|
ExprKind::Let(ref pat, ref scrutinee, _, _) => {
|
||||||
self.visit_expr(scrutinee);
|
self.visit_expr(scrutinee);
|
||||||
self.resolve_pattern_top(pat, PatternSource::Let);
|
self.resolve_pattern_top(pat, PatternSource::Let);
|
||||||
}
|
}
|
||||||
|
|
|
@ -586,7 +586,7 @@ fn ident_difference_expr_with_base_location(
|
||||||
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
|
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
|
||||||
| (While(_, _, _), While(_, _, _))
|
| (While(_, _, _), While(_, _, _))
|
||||||
| (If(_, _, _), If(_, _, _))
|
| (If(_, _, _), If(_, _, _))
|
||||||
| (Let(_, _, _), Let(_, _, _))
|
| (Let(_, _, _, _), Let(_, _, _, _))
|
||||||
| (Type(_, _), Type(_, _))
|
| (Type(_, _), Type(_, _))
|
||||||
| (Cast(_, _), Cast(_, _))
|
| (Cast(_, _), Cast(_, _))
|
||||||
| (Lit(_), Lit(_))
|
| (Lit(_), Lit(_))
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl EarlyLintPass for UnnestedOrPatterns {
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||||
if self.msrv.meets(msrvs::OR_PATTERNS) {
|
if self.msrv.meets(msrvs::OR_PATTERNS) {
|
||||||
if let ast::ExprKind::Let(pat, _, _) = &e.kind {
|
if let ast::ExprKind::Let(pat, _, _, _) = &e.kind {
|
||||||
lint_unnested_or_patterns(cx, pat);
|
lint_unnested_or_patterns(cx, pat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
||||||
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
|
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
|
||||||
(Lit(l), Lit(r)) => l == r,
|
(Lit(l), Lit(r)) => l == r,
|
||||||
(Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt),
|
(Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt),
|
||||||
(Let(lp, le, _), Let(rp, re, _)) => eq_pat(lp, rp) && eq_expr(le, re),
|
(Let(lp, le, _, _), Let(rp, re, _, _)) => eq_pat(lp, rp) && eq_expr(le, re),
|
||||||
(If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re),
|
(If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re),
|
||||||
(While(lc, lt, ll), While(rc, rt, rl)) => eq_label(ll, rl) && eq_expr(lc, rc) && eq_block(lt, rt),
|
(While(lc, lt, ll), While(rc, rt, rl)) => eq_label(ll, rl) && eq_expr(lc, rc) && eq_block(lt, rt),
|
||||||
(ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
|
(ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
|
||||||
|
|
|
@ -664,7 +664,7 @@ struct ControlFlow<'a> {
|
||||||
|
|
||||||
fn extract_pats_and_cond(expr: &ast::Expr) -> (Option<&ast::Pat>, &ast::Expr) {
|
fn extract_pats_and_cond(expr: &ast::Expr) -> (Option<&ast::Pat>, &ast::Expr) {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ast::ExprKind::Let(ref pat, ref cond, _) => (Some(pat), cond),
|
ast::ExprKind::Let(ref pat, ref cond, _, _) => (Some(pat), cond),
|
||||||
_ => (None, expr),
|
_ => (None, expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,14 +80,20 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
|
||||||
let seg = PathSegment::from_ident(Ident::from_str("x"));
|
let seg = PathSegment::from_ident(Ident::from_str("x"));
|
||||||
iter_exprs(depth - 1, &mut |e| {
|
iter_exprs(depth - 1, &mut |e| {
|
||||||
g(ExprKind::MethodCall(Box::new(MethodCall {
|
g(ExprKind::MethodCall(Box::new(MethodCall {
|
||||||
seg: seg.clone(), receiver: e, args: thin_vec![make_x()], span: DUMMY_SP
|
seg: seg.clone(),
|
||||||
}))
|
receiver: e,
|
||||||
)});
|
args: thin_vec![make_x()],
|
||||||
|
span: DUMMY_SP,
|
||||||
|
})))
|
||||||
|
});
|
||||||
iter_exprs(depth - 1, &mut |e| {
|
iter_exprs(depth - 1, &mut |e| {
|
||||||
g(ExprKind::MethodCall(Box::new(MethodCall {
|
g(ExprKind::MethodCall(Box::new(MethodCall {
|
||||||
seg: seg.clone(), receiver: make_x(), args: thin_vec![e], span: DUMMY_SP
|
seg: seg.clone(),
|
||||||
}))
|
receiver: make_x(),
|
||||||
)});
|
args: thin_vec![e],
|
||||||
|
span: DUMMY_SP,
|
||||||
|
})))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
2..=7 => {
|
2..=7 => {
|
||||||
let op = Spanned {
|
let op = Spanned {
|
||||||
|
@ -174,7 +180,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
|
||||||
18 => {
|
18 => {
|
||||||
let pat =
|
let pat =
|
||||||
P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Wild, span: DUMMY_SP, tokens: None });
|
P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Wild, span: DUMMY_SP, tokens: None });
|
||||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e, DUMMY_SP)))
|
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e, DUMMY_SP, None)))
|
||||||
}
|
}
|
||||||
_ => panic!("bad counter value in iter_exprs"),
|
_ => panic!("bad counter value in iter_exprs"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
fn a() {
|
fn a() {
|
||||||
if let x = 1 && i = 2 {}
|
if let x = 1 && i = 2 {}
|
||||||
//~^ ERROR cannot find value `i` in this scope
|
//~^ ERROR cannot find value `i` in this scope
|
||||||
//~| ERROR `let` expressions in this position are unstable
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| ERROR `let` expressions are not supported here
|
//~| ERROR expected expression, found `let` statement
|
||||||
}
|
}
|
||||||
|
|
||||||
fn b() {
|
fn b() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: `let` expressions are not supported here
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/bad-if-let-suggestion.rs:5:8
|
--> $DIR/bad-if-let-suggestion.rs:5:8
|
||||||
|
|
|
|
||||||
LL | if let x = 1 && i = 2 {}
|
LL | if let x = 1 && i = 2 {}
|
||||||
|
@ -13,7 +13,7 @@ LL | if let x = 1 && i = 2 {}
|
||||||
| ^ not found in this scope
|
| ^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `i` in this scope
|
error[E0425]: cannot find value `i` in this scope
|
||||||
--> $DIR/bad-if-let-suggestion.rs:13:9
|
--> $DIR/bad-if-let-suggestion.rs:12:9
|
||||||
|
|
|
|
||||||
LL | fn a() {
|
LL | fn a() {
|
||||||
| ------ similarly named function `a` defined here
|
| ------ similarly named function `a` defined here
|
||||||
|
@ -22,7 +22,7 @@ LL | if (i + j) = i {}
|
||||||
| ^ help: a function with a similar name exists: `a`
|
| ^ help: a function with a similar name exists: `a`
|
||||||
|
|
||||||
error[E0425]: cannot find value `j` in this scope
|
error[E0425]: cannot find value `j` in this scope
|
||||||
--> $DIR/bad-if-let-suggestion.rs:13:13
|
--> $DIR/bad-if-let-suggestion.rs:12:13
|
||||||
|
|
|
|
||||||
LL | fn a() {
|
LL | fn a() {
|
||||||
| ------ similarly named function `a` defined here
|
| ------ similarly named function `a` defined here
|
||||||
|
@ -31,7 +31,7 @@ LL | if (i + j) = i {}
|
||||||
| ^ help: a function with a similar name exists: `a`
|
| ^ help: a function with a similar name exists: `a`
|
||||||
|
|
||||||
error[E0425]: cannot find value `i` in this scope
|
error[E0425]: cannot find value `i` in this scope
|
||||||
--> $DIR/bad-if-let-suggestion.rs:13:18
|
--> $DIR/bad-if-let-suggestion.rs:12:18
|
||||||
|
|
|
|
||||||
LL | fn a() {
|
LL | fn a() {
|
||||||
| ------ similarly named function `a` defined here
|
| ------ similarly named function `a` defined here
|
||||||
|
@ -40,7 +40,7 @@ LL | if (i + j) = i {}
|
||||||
| ^ help: a function with a similar name exists: `a`
|
| ^ help: a function with a similar name exists: `a`
|
||||||
|
|
||||||
error[E0425]: cannot find value `x` in this scope
|
error[E0425]: cannot find value `x` in this scope
|
||||||
--> $DIR/bad-if-let-suggestion.rs:20:8
|
--> $DIR/bad-if-let-suggestion.rs:19:8
|
||||||
|
|
|
|
||||||
LL | fn a() {
|
LL | fn a() {
|
||||||
| ------ similarly named function `a` defined here
|
| ------ similarly named function `a` defined here
|
||||||
|
@ -48,15 +48,6 @@ LL | fn a() {
|
||||||
LL | if x[0] = 1 {}
|
LL | if x[0] = 1 {}
|
||||||
| ^ help: a function with a similar name exists: `a`
|
| ^ help: a function with a similar name exists: `a`
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/bad-if-let-suggestion.rs:5:8
|
|
||||||
|
|
|
||||||
LL | if let x = 1 && i = 2 {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= 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[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/bad-if-let-suggestion.rs:5:8
|
--> $DIR/bad-if-let-suggestion.rs:5:8
|
||||||
|
|
|
|
||||||
|
@ -68,7 +59,7 @@ help: you might have meant to compare for equality
|
||||||
LL | if let x = 1 && i == 2 {}
|
LL | if let x = 1 && i == 2 {}
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0308, E0425, E0658.
|
Some errors have detailed explanations: E0308, E0425.
|
||||||
For more information about an error, try `rustc --explain E0308`.
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
struct Bug<A = [(); (let a = (), 1).1]> {
|
struct Bug<A = [(); (let a = (), 1).1]> {
|
||||||
//~^ `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| `let` expressions in this position are unstable [E0658]
|
|
||||||
//~| expected expression, found `let` statement
|
|
||||||
a: A
|
a: A
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,24 +3,8 @@ error: expected expression, found `let` statement
|
||||||
|
|
|
|
||||||
LL | struct Bug<A = [(); (let a = (), 1).1]> {
|
LL | struct Bug<A = [(); (let a = (), 1).1]> {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/issue-92893.rs:1:22
|
|
||||||
|
|
|
||||||
LL | struct Bug<A = [(); (let a = (), 1).1]> {
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
error: aborting due to previous error
|
||||||
--> $DIR/issue-92893.rs:1:22
|
|
||||||
|
|
|
||||||
LL | struct Bug<A = [(); (let a = (), 1).1]> {
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
||||||
|
|
|
@ -8,14 +8,10 @@ fn _if_let_guard() {
|
||||||
//~^ ERROR `if let` guards are experimental
|
//~^ ERROR `if let` guards are experimental
|
||||||
|
|
||||||
() if (let 0 = 1) => {}
|
() if (let 0 = 1) => {}
|
||||||
//~^ ERROR `let` expressions in this position are unstable
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
|
|
||||||
() if (((let 0 = 1))) => {}
|
() if (((let 0 = 1))) => {}
|
||||||
//~^ ERROR `let` expressions in this position are unstable
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
|
|
||||||
() if true && let 0 = 1 => {}
|
() if true && let 0 = 1 => {}
|
||||||
//~^ ERROR `if let` guards are experimental
|
//~^ ERROR `if let` guards are experimental
|
||||||
|
@ -26,36 +22,22 @@ fn _if_let_guard() {
|
||||||
//~| ERROR `let` expressions in this position are unstable
|
//~| ERROR `let` expressions in this position are unstable
|
||||||
|
|
||||||
() if (let 0 = 1) && true => {}
|
() if (let 0 = 1) && true => {}
|
||||||
//~^ ERROR `let` expressions in this position are unstable
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
|
|
||||||
() if true && (let 0 = 1) => {}
|
() if true && (let 0 = 1) => {}
|
||||||
//~^ ERROR `let` expressions in this position are unstable
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
|
|
||||||
() if (let 0 = 1) && (let 0 = 1) => {}
|
() if (let 0 = 1) && (let 0 = 1) => {}
|
||||||
//~^ ERROR `let` expressions in this position are unstable
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions in this position are unstable
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
|
|
||||||
() 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
|
||||||
//~| 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 `let` expressions in this position are unstable
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
|
|
||||||
|
|
||||||
() if let Range { start: _, end: _ } = (true..true) && false => {}
|
() if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||||
|
@ -76,13 +58,9 @@ 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 expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
use_expr!((let 0 = 1));
|
use_expr!((let 0 = 1));
|
||||||
//~^ ERROR `let` expressions in this position are unstable
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
match () {
|
match () {
|
||||||
#[cfg(FALSE)]
|
#[cfg(FALSE)]
|
||||||
() if let 0 = 1 => {}
|
() if let 0 = 1 => {}
|
||||||
|
|
|
@ -2,70 +2,137 @@ error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:10:16
|
--> $DIR/feature-gate.rs:10:16
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
LL | () if (let 0 = 1) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:10:16
|
||||||
|
|
|
||||||
|
LL | () if (let 0 = 1) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:15:18
|
--> $DIR/feature-gate.rs:13:18
|
||||||
|
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
LL | () if (((let 0 = 1))) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:13:18
|
||||||
|
|
|
||||||
|
LL | () if (((let 0 = 1))) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:28:16
|
--> $DIR/feature-gate.rs:24:16
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) && true => {}
|
LL | () if (let 0 = 1) && true => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:24:16
|
||||||
|
|
|
||||||
|
LL | () if (let 0 = 1) && true => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:33:24
|
--> $DIR/feature-gate.rs:27:24
|
||||||
|
|
|
|
||||||
LL | () if true && (let 0 = 1) => {}
|
LL | () if true && (let 0 = 1) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:27:24
|
||||||
|
|
|
||||||
|
LL | () if true && (let 0 = 1) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:38:16
|
--> $DIR/feature-gate.rs:30:16
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
error: expected expression, found `let` statement
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
--> $DIR/feature-gate.rs:38:31
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:30:16
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:46:42
|
--> $DIR/feature-gate.rs:30:31
|
||||||
|
|
|
||||||
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:30:31
|
||||||
|
|
|
||||||
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: expected expression, found `let` statement
|
||||||
|
--> $DIR/feature-gate.rs:34: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) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
error: expected expression, found `let` statement
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
--> $DIR/feature-gate.rs:46:55
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:34: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) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:46:68
|
--> $DIR/feature-gate.rs:34: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) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:34:42
|
||||||
|
|
|
||||||
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:78:16
|
--> $DIR/feature-gate.rs:34:68
|
||||||
|
|
|
||||||
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/feature-gate.rs:34: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:60:16
|
||||||
|
|
|
|
||||||
LL | use_expr!((let 0 = 1 && 0 == 0));
|
LL | use_expr!((let 0 = 1 && 0 == 0));
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:82:16
|
--> $DIR/feature-gate.rs:62:16
|
||||||
|
|
|
|
||||||
LL | use_expr!((let 0 = 1));
|
LL | use_expr!((let 0 = 1));
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: no rules expected the token `let`
|
error: no rules expected the token `let`
|
||||||
--> $DIR/feature-gate.rs:92:15
|
--> $DIR/feature-gate.rs:70:15
|
||||||
|
|
|
|
||||||
LL | macro_rules! use_expr {
|
LL | macro_rules! use_expr {
|
||||||
| --------------------- when calling this macro
|
| --------------------- when calling this macro
|
||||||
|
@ -74,154 +141,11 @@ LL | use_expr!(let 0 = 1);
|
||||||
| ^^^ no rules expected this token in macro call
|
| ^^^ no rules expected this token in macro call
|
||||||
|
|
|
|
||||||
note: while trying to match meta-variable `$e:expr`
|
note: while trying to match meta-variable `$e:expr`
|
||||||
--> $DIR/feature-gate.rs:71:10
|
--> $DIR/feature-gate.rs:53:10
|
||||||
|
|
|
|
||||||
LL | ($e:expr) => {
|
LL | ($e:expr) => {
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:10:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:10:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:15:18
|
|
||||||
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:15:18
|
|
||||||
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:28:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && true => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:28:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && true => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:33:24
|
|
||||||
|
|
|
||||||
LL | () if true && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:33:24
|
|
||||||
|
|
|
||||||
LL | () if true && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:38:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:38:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:38:31
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:38:31
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:46:42
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:46:42
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:46:55
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:46:42
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:46:68
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:46:42
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:78:16
|
|
||||||
|
|
|
||||||
LL | use_expr!((let 0 = 1 && 0 == 0));
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:78:16
|
|
||||||
|
|
|
||||||
LL | use_expr!((let 0 = 1 && 0 == 0));
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/feature-gate.rs:82:16
|
|
||||||
|
|
|
||||||
LL | use_expr!((let 0 = 1));
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
|
||||||
--> $DIR/feature-gate.rs:82:16
|
|
||||||
|
|
|
||||||
LL | use_expr!((let 0 = 1));
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0658]: `if let` guards are experimental
|
error[E0658]: `if let` guards are experimental
|
||||||
--> $DIR/feature-gate.rs:7:12
|
--> $DIR/feature-gate.rs:7:12
|
||||||
|
|
|
|
||||||
|
@ -233,7 +157,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:20:12
|
--> $DIR/feature-gate.rs:16:12
|
||||||
|
|
|
|
||||||
LL | () if true && let 0 = 1 => {}
|
LL | () if true && let 0 = 1 => {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -243,7 +167,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:24:12
|
--> $DIR/feature-gate.rs:20:12
|
||||||
|
|
|
|
||||||
LL | () if let 0 = 1 && true => {}
|
LL | () if let 0 = 1 && true => {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -253,7 +177,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:46:12
|
--> $DIR/feature-gate.rs:34: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) => {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -263,7 +187,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:61:12
|
--> $DIR/feature-gate.rs:43:12
|
||||||
|
|
|
|
||||||
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -273,7 +197,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:88:12
|
--> $DIR/feature-gate.rs:66:12
|
||||||
|
|
|
|
||||||
LL | () if let 0 = 1 => {}
|
LL | () if let 0 = 1 => {}
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -283,25 +207,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]: `let` expressions in this position are unstable
|
error[E0658]: `let` expressions in this position are unstable
|
||||||
--> $DIR/feature-gate.rs:10:16
|
--> $DIR/feature-gate.rs:16:23
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/feature-gate.rs:15:18
|
|
||||||
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/feature-gate.rs:20:23
|
|
||||||
|
|
|
|
||||||
LL | () if true && let 0 = 1 => {}
|
LL | () if true && let 0 = 1 => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -310,7 +216,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:24:15
|
--> $DIR/feature-gate.rs:20:15
|
||||||
|
|
|
|
||||||
LL | () if let 0 = 1 && true => {}
|
LL | () if let 0 = 1 && true => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -319,43 +225,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:28:16
|
--> $DIR/feature-gate.rs:34:15
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && true => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= 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:33:24
|
|
||||||
|
|
|
||||||
LL | () if true && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/feature-gate.rs:38:16
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/feature-gate.rs:38:31
|
|
||||||
|
|
|
||||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/feature-gate.rs:46: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) => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -364,7 +234,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:46:28
|
--> $DIR/feature-gate.rs:34: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) => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -373,34 +243,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:46:42
|
--> $DIR/feature-gate.rs:43:15
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= 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:46:55
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= 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:46:68
|
|
||||||
|
|
|
||||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= 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:61:15
|
|
||||||
|
|
|
|
||||||
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -408,24 +251,6 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||||
= 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[E0658]: `let` expressions in this position are unstable
|
error: aborting due to 23 previous errors
|
||||||
--> $DIR/feature-gate.rs:78:16
|
|
||||||
|
|
|
||||||
LL | use_expr!((let 0 = 1 && 0 == 0));
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= 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:82:16
|
|
||||||
|
|
|
||||||
LL | use_expr!((let 0 = 1));
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 45 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
|
@ -7,6 +7,7 @@ LL | ($e:expr) => { let Some(x) = $e }
|
||||||
LL | () if m!(Some(5)) => {}
|
LL | () if m!(Some(5)) => {}
|
||||||
| ----------- in this macro invocation
|
| ----------- in this macro invocation
|
||||||
|
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -19,9 +19,7 @@ fn main() {
|
||||||
() if let 0 = 1 => {}
|
() if let 0 = 1 => {}
|
||||||
() if (let 0 = 1) => {}
|
() if (let 0 = 1) => {}
|
||||||
//~^ ERROR expected expression, found `let` statement
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
() if (((let 0 = 1))) => {}
|
() if (((let 0 = 1))) => {}
|
||||||
//~^ ERROR expected expression, found `let` statement
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,29 @@ error: expected expression, found `let` statement
|
||||||
--> $DIR/parens.rs:10:16
|
--> $DIR/parens.rs:10:16
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
LL | () if (let 0 = 1) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/parens.rs:10:16
|
||||||
|
|
|
||||||
|
LL | () if (let 0 = 1) => {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/parens.rs:12:18
|
--> $DIR/parens.rs:12:18
|
||||||
|
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
LL | () if (((let 0 = 1))) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
|
||||||
--> $DIR/parens.rs:20:16
|
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
| ^^^
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
|
--> $DIR/parens.rs:12:18
|
||||||
error: expected expression, found `let` statement
|
|
||||||
--> $DIR/parens.rs:23:18
|
|
||||||
|
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
LL | () if (((let 0 = 1))) => {}
|
||||||
| ^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/parens.rs:20:16
|
--> $DIR/parens.rs:20:16
|
||||||
|
|
|
|
||||||
LL | () if (let 0 = 1) => {}
|
LL | () if (let 0 = 1) => {}
|
||||||
|
@ -35,18 +37,18 @@ note: `let`s wrapped in parentheses are not supported in a context with let chai
|
||||||
LL | () if (let 0 = 1) => {}
|
LL | () if (let 0 = 1) => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/parens.rs:23:18
|
--> $DIR/parens.rs:22:18
|
||||||
|
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
LL | () if (((let 0 = 1))) => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
note: `let`s wrapped in parentheses are not supported in a context with let chains
|
||||||
--> $DIR/parens.rs:23:18
|
--> $DIR/parens.rs:22:18
|
||||||
|
|
|
|
||||||
LL | () if (((let 0 = 1))) => {}
|
LL | () if (((let 0 = 1))) => {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
fn let_or_guard(x: Result<Option<i32>, ()>) {
|
fn let_or_guard(x: Result<Option<i32>, ()>) {
|
||||||
match x {
|
match x {
|
||||||
Ok(opt) if let Some(4) = opt || false => {}
|
Ok(opt) if let Some(4) = opt || false => {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: `let` expressions are not supported here
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/ast-validate-guards.rs:5:20
|
--> $DIR/ast-validate-guards.rs:5:20
|
||||||
|
|
|
|
||||||
LL | Ok(opt) if let Some(4) = opt || false => {}
|
LL | Ok(opt) if let Some(4) = opt || false => {}
|
||||||
|
|
14
tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.rs
Normal file
14
tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Regression test for #104172
|
||||||
|
|
||||||
|
const N: usize = {
|
||||||
|
struct U;
|
||||||
|
!let y = 42;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
x: [(); N]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,10 @@
|
||||||
|
error: expected expression, found `let` statement
|
||||||
|
--> $DIR/avoid-invalid-mir.rs:5:6
|
||||||
|
|
|
||||||
|
LL | !let y = 42;
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
// Check that we don't suggest enabling a feature for code that's
|
||||||
|
// not accepted even with that feature.
|
||||||
|
|
||||||
|
#![allow(irrefutable_let_patterns)]
|
||||||
|
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
fn _if() {
|
||||||
|
if (let 0 = 1) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if (((let 0 = 1))) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if (let 0 = 1) && true {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if true && (let 0 = 1) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if (let 0 = 1) && (let 0 = 1) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _while() {
|
||||||
|
while (let 0 = 1) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while (((let 0 = 1))) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while (let 0 = 1) && true {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while true && (let 0 = 1) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while (let 0 = 1) && (let 0 = 1) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _macros() {
|
||||||
|
macro_rules! use_expr {
|
||||||
|
($e:expr) => {
|
||||||
|
if $e {}
|
||||||
|
while $e {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use_expr!((let 0 = 1 && 0 == 0));
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
use_expr!((let 0 = 1));
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nested_within_if_expr() {
|
||||||
|
if &let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if !let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
if *let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
if -let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
fn _check_try_binds_tighter() -> Result<(), ()> {
|
||||||
|
if let 0 = 0? {}
|
||||||
|
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
if (let 0 = 0)? {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if true || let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
if (true || let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
if true && (true || let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
if true || (true && let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
let mut x = true;
|
||||||
|
if x = let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
if true..(let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
if ..(let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
if (let 0 = 0).. {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
// Binds as `(let ... = true)..true &&/|| false`.
|
||||||
|
if let Range { start: _, end: _ } = true..true && false {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
if let Range { start: _, end: _ } = true..true || false {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
|
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
||||||
|
const F: fn() -> bool = || true;
|
||||||
|
if let Range { start: F, end } = F..|| true {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
|
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
||||||
|
let t = &&true;
|
||||||
|
if let Range { start: true, end } = t..&&false {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
|
if let true = let true = true {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nested_within_while_expr() {
|
||||||
|
while &let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while !let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
while *let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
while -let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
fn _check_try_binds_tighter() -> Result<(), ()> {
|
||||||
|
while let 0 = 0? {}
|
||||||
|
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
while (let 0 = 0)? {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while true || let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
while (true || let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
while true && (true || let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
while true || (true && let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
let mut x = true;
|
||||||
|
while x = let 0 = 0 {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
while true..(let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
while ..(let 0 = 0) {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
while (let 0 = 0).. {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
// Binds as `(let ... = true)..true &&/|| false`.
|
||||||
|
while let Range { start: _, end: _ } = true..true && false {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
while let Range { start: _, end: _ } = true..true || false {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
|
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
||||||
|
const F: fn() -> bool = || true;
|
||||||
|
while let Range { start: F, end } = F..|| true {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
|
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
||||||
|
let t = &&true;
|
||||||
|
while let Range { start: true, end } = t..&&false {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
|
while let true = let true = true {}
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_error_because_clarified_intent() {
|
||||||
|
if let Range { start: _, end: _ } = (true..true || false) { }
|
||||||
|
|
||||||
|
if let Range { start: _, end: _ } = (true..true && false) { }
|
||||||
|
|
||||||
|
while let Range { start: _, end: _ } = (true..true || false) { }
|
||||||
|
|
||||||
|
while let Range { start: _, end: _ } = (true..true && false) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn outside_if_and_while_expr() {
|
||||||
|
&let 0 = 0;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
!let 0 = 0;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
*let 0 = 0;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
-let 0 = 0;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
let _ = let _ = 3;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
fn _check_try_binds_tighter() -> Result<(), ()> {
|
||||||
|
let 0 = 0?;
|
||||||
|
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
(let 0 = 0)?;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
true || let 0 = 0;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
(true || let 0 = 0);
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
true && (true || let 0 = 0);
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
let mut x = true;
|
||||||
|
x = let 0 = 0;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
true..(let 0 = 0);
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
..(let 0 = 0);
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
(let 0 = 0)..;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
(let Range { start: _, end: _ } = true..true || false);
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
(let true = let true = true);
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
{
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
let x = true && let y = 1;
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
{
|
||||||
|
[1, 2, 3][let _ = ()]
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check function tail position.
|
||||||
|
&let 0 = 0
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's make sure that `let` inside const generic arguments are considered.
|
||||||
|
fn inside_const_generic_arguments() {
|
||||||
|
struct A<const B: bool>;
|
||||||
|
impl<const B: bool> A<{B}> { const O: u32 = 5; }
|
||||||
|
|
||||||
|
if let A::<{
|
||||||
|
true && let 1 = 1
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}>::O = 5 {}
|
||||||
|
|
||||||
|
while let A::<{
|
||||||
|
true && let 1 = 1
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}>::O = 5 {}
|
||||||
|
|
||||||
|
if A::<{
|
||||||
|
true && let 1 = 1
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}>::O == 5 {}
|
||||||
|
|
||||||
|
// In the cases above we have `ExprKind::Block` to help us out.
|
||||||
|
// Below however, we would not have a block and so an implementation might go
|
||||||
|
// from visiting expressions to types without banning `let` expressions down the tree.
|
||||||
|
// This tests ensures that we are not caught by surprise should the parser
|
||||||
|
// admit non-IDENT expressions in const generic arguments.
|
||||||
|
|
||||||
|
if A::<
|
||||||
|
true && let 1 = 1
|
||||||
|
//~^ ERROR expressions must be enclosed in braces
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
>::O == 5 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_parenthesis() {
|
||||||
|
let opt = Some(Some(1i32));
|
||||||
|
|
||||||
|
if (let Some(a) = opt && true) {
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
if (let Some(a) = opt) && true {
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
if (let Some(a) = opt) && (let Some(b) = a) {
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
if (let Some(a) = opt && (let Some(b) = a)) && true {
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
if (let Some(a) = opt && (true)) && true {
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
let x = (true && let y = 1);
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
{
|
||||||
|
([1, 2, 3][let _ = ()])
|
||||||
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -27,64 +27,46 @@ fn main() {}
|
||||||
|
|
||||||
fn _if() {
|
fn _if() {
|
||||||
if (let 0 = 1) {}
|
if (let 0 = 1) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
if (((let 0 = 1))) {}
|
if (((let 0 = 1))) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
if (let 0 = 1) && true {}
|
if (let 0 = 1) && true {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
if true && (let 0 = 1) {}
|
if true && (let 0 = 1) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| 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
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| 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 expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
while (((let 0 = 1))) {}
|
while (((let 0 = 1))) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
while (let 0 = 1) && true {}
|
while (let 0 = 1) && true {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
while true && (let 0 = 1) {}
|
while true && (let 0 = 1) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| 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
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
}
|
}
|
||||||
|
@ -97,32 +79,21 @@ fn _macros() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
use_expr!((let 0 = 1 && 0 == 0));
|
use_expr!((let 0 = 1 && 0 == 0));
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nested_within_if_expr() {
|
fn nested_within_if_expr() {
|
||||||
if &let 0 = 0 {}
|
if &let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
if !let 0 = 0 {}
|
if !let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if *let 0 = 0 {}
|
if *let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR type `bool` cannot be dereferenced
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if -let 0 = 0 {}
|
if -let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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? {}
|
||||||
|
@ -130,91 +101,63 @@ fn nested_within_if_expr() {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
if (let 0 = 0)? {}
|
if (let 0 = 0)? {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR the `?` operator can only be applied to values that implement `Try`
|
|
||||||
//~| ERROR the `?` operator can only be used in a function that returns `Result`
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
if true || let 0 = 0 {}
|
if true || let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if (true || let 0 = 0) {}
|
if (true || let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if true && (true || let 0 = 0) {}
|
if true && (true || let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if true || (true && let 0 = 0) {}
|
if true || (true && let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
let mut x = true;
|
let mut x = true;
|
||||||
if x = let 0 = 0 {}
|
if x = let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
if true..(let 0 = 0) {}
|
if true..(let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if ..(let 0 = 0) {}
|
if ..(let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
if (let 0 = 0).. {}
|
if (let 0 = 0).. {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
if let Range { start: _, end: _ } = true..true || false {}
|
if let Range { start: _, end: _ } = true..true || false {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
||||||
const F: fn() -> bool = || true;
|
const F: fn() -> bool = || true;
|
||||||
if let Range { start: F, end } = F..|| true {}
|
if let Range { start: F, end } = F..|| true {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
||||||
let t = &&true;
|
let t = &&true;
|
||||||
if let Range { start: true, end } = t..&&false {}
|
if let Range { start: true, end } = t..&&false {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
if let true = let true = true {}
|
if let true = let true = true {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nested_within_while_expr() {
|
fn nested_within_while_expr() {
|
||||||
while &let 0 = 0 {}
|
while &let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
while !let 0 = 0 {}
|
while !let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while *let 0 = 0 {}
|
while *let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR type `bool` cannot be dereferenced
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while -let 0 = 0 {}
|
while -let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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? {}
|
||||||
|
@ -222,72 +165,51 @@ fn nested_within_while_expr() {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
while (let 0 = 0)? {}
|
while (let 0 = 0)? {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR the `?` operator can only be applied to values that implement `Try`
|
|
||||||
//~| ERROR the `?` operator can only be used in a function that returns `Result`
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
while true || let 0 = 0 {}
|
while true || let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while (true || let 0 = 0) {}
|
while (true || let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while true && (true || let 0 = 0) {}
|
while true && (true || let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while true || (true && let 0 = 0) {}
|
while true || (true && let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
let mut x = true;
|
let mut x = true;
|
||||||
while x = let 0 = 0 {}
|
while x = let 0 = 0 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
while true..(let 0 = 0) {}
|
while true..(let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while ..(let 0 = 0) {}
|
while ..(let 0 = 0) {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
while (let 0 = 0).. {}
|
while (let 0 = 0).. {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
while let Range { start: _, end: _ } = true..true || false {}
|
while let Range { start: _, end: _ } = true..true || false {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
// Binds as `(let Range { start: F, end } = F)..(|| true)`.
|
||||||
const F: fn() -> bool = || true;
|
const F: fn() -> bool = || true;
|
||||||
while let Range { start: F, end } = F..|| true {}
|
while let Range { start: F, end } = F..|| true {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
// Binds as `(let Range { start: true, end } = t)..(&&false)`.
|
||||||
let t = &&true;
|
let t = &&true;
|
||||||
while let Range { start: true, end } = t..&&false {}
|
while let Range { start: true, end } = t..&&false {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
while let true = let true = true {}
|
while let true = let true = true {}
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not_error_because_clarified_intent() {
|
fn not_error_because_clarified_intent() {
|
||||||
|
@ -302,20 +224,14 @@ fn not_error_because_clarified_intent() {
|
||||||
|
|
||||||
fn outside_if_and_while_expr() {
|
fn outside_if_and_while_expr() {
|
||||||
&let 0 = 0;
|
&let 0 = 0;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
!let 0 = 0;
|
!let 0 = 0;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
*let 0 = 0;
|
*let 0 = 0;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR type `bool` cannot be dereferenced
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
-let 0 = 0;
|
-let 0 = 0;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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?;
|
||||||
|
@ -323,44 +239,32 @@ fn outside_if_and_while_expr() {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(let 0 = 0)?;
|
(let 0 = 0)?;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 expected expression, found `let` statement
|
|
||||||
|
|
||||||
true || let 0 = 0;
|
true || let 0 = 0;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
(true || let 0 = 0);
|
(true || let 0 = 0);
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
true && (true || let 0 = 0);
|
true && (true || let 0 = 0);
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
let mut x = true;
|
let mut x = true;
|
||||||
x = let 0 = 0;
|
x = let 0 = 0;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
true..(let 0 = 0);
|
true..(let 0 = 0);
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
..(let 0 = 0);
|
..(let 0 = 0);
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
(let 0 = 0)..;
|
(let 0 = 0)..;
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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 mismatched types
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
(let true = let true = true);
|
(let true = let true = true);
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -377,9 +281,7 @@ fn outside_if_and_while_expr() {
|
||||||
|
|
||||||
// Check function tail position.
|
// Check function tail position.
|
||||||
&let 0 = 0
|
&let 0 = 0
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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.
|
||||||
|
@ -389,20 +291,17 @@ fn inside_const_generic_arguments() {
|
||||||
|
|
||||||
if let A::<{
|
if let A::<{
|
||||||
true && let 1 = 1
|
true && let 1 = 1
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}>::O = 5 {}
|
}>::O = 5 {}
|
||||||
|
|
||||||
while let A::<{
|
while let A::<{
|
||||||
true && let 1 = 1
|
true && let 1 = 1
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}>::O = 5 {}
|
}>::O = 5 {}
|
||||||
|
|
||||||
if A::<{
|
if A::<{
|
||||||
true && let 1 = 1
|
true && let 1 = 1
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}>::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.
|
||||||
|
@ -413,8 +312,7 @@ fn inside_const_generic_arguments() {
|
||||||
|
|
||||||
if A::<
|
if A::<
|
||||||
true && let 1 = 1
|
true && let 1 = 1
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expressions must be enclosed in braces
|
||||||
//~| ERROR expressions must be enclosed in braces
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
>::O == 5 {}
|
>::O == 5 {}
|
||||||
}
|
}
|
||||||
|
@ -423,38 +321,29 @@ fn with_parenthesis() {
|
||||||
let opt = Some(Some(1i32));
|
let opt = Some(Some(1i32));
|
||||||
|
|
||||||
if (let Some(a) = opt && true) {
|
if (let Some(a) = opt && true) {
|
||||||
//~^ 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 {
|
if (let Some(a) = opt) && true {
|
||||||
//~^ 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) {
|
if (let Some(a) = opt) && (let Some(b) = a) {
|
||||||
//~^ ERROR `let` expressions are not supported here
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| 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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| ERROR `let` expressions are not supported here
|
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
//~| 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 expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true && (true)) && let Some(a) = opt {
|
if (true && (true)) && let Some(a) = opt {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,6 @@ fn main() {
|
||||||
};
|
};
|
||||||
let Some(n) = opt && let another = n else {
|
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`
|
||||||
//~| 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
|
//~| ERROR expected expression, found `let` statement
|
||||||
|
|
|
@ -14,6 +14,8 @@ error: expected expression, found `let` statement
|
||||||
|
|
|
|
||||||
LL | let Some(n) = opt && let another = n else {
|
LL | let Some(n) = opt && let another = n else {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
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
|
||||||
|
@ -27,13 +29,13 @@ 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:24:5
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23: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:24:25
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25
|
||||||
|
|
|
|
||||||
LL | if let Some(n) = opt else {
|
LL | if let Some(n) = opt else {
|
||||||
| ^
|
| ^
|
||||||
|
@ -44,31 +46,31 @@ LL + 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:28:5
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27: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:28:35
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27: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:32:5
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31: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:32:44
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31: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:38:33
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33
|
||||||
|
|
|
|
||||||
LL | while let Some(n) = opt else {
|
LL | while let Some(n) = opt else {
|
||||||
| ----- ----------------- ^^^^ expected `{`
|
| ----- ----------------- ^^^^ expected `{`
|
||||||
|
@ -77,7 +79,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:44:43
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:43:43
|
||||||
|
|
|
|
||||||
LL | while let Some(n) = opt && n == 1 else {
|
LL | while let Some(n) = opt && n == 1 else {
|
||||||
| ----- --------------------------- ^^^^ expected `{`
|
| ----- --------------------------- ^^^^ expected `{`
|
||||||
|
@ -86,7 +88,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:50:52
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:49:52
|
||||||
|
|
|
|
||||||
LL | while let Some(n) = opt && let another = n else {
|
LL | while let Some(n) = opt && let another = n else {
|
||||||
| ----- ------------------------------------ ^^^^ expected `{`
|
| ----- ------------------------------------ ^^^^ expected `{`
|
||||||
|
@ -94,14 +96,6 @@ LL | while let Some(n) = opt && let another = n else {
|
||||||
| | this `while` condition successfully parsed
|
| | this `while` condition successfully parsed
|
||||||
| while parsing the body of this `while` expression
|
| while parsing the body of this `while` expression
|
||||||
|
|
||||||
error: `let` expressions are not supported here
|
|
||||||
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26
|
|
||||||
|
|
|
||||||
LL | let Some(n) = opt && let another = n else {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: only supported directly in conditions of `if` and `while` expressions
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
|
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
|
||||||
|
|
|
|
||||||
|
@ -142,6 +136,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 14 previous errors
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -43,8 +43,7 @@ fn _macros() {
|
||||||
macro_rules! noop_expr { ($e:expr) => {}; }
|
macro_rules! noop_expr { ($e:expr) => {}; }
|
||||||
|
|
||||||
noop_expr!((let 0 = 1));
|
noop_expr!((let 0 = 1));
|
||||||
//~^ ERROR `let` expressions in this position are unstable [E0658]
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
|
||||||
|
|
||||||
macro_rules! use_expr {
|
macro_rules! use_expr {
|
||||||
($e:expr) => {
|
($e:expr) => {
|
||||||
|
@ -53,8 +52,7 @@ fn _macros() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(FALSE)] (let 0 = 1);
|
#[cfg(FALSE)] (let 0 = 1);
|
||||||
//~^ ERROR `let` expressions in this position are unstable [E0658]
|
//~^ ERROR expected expression, found `let` statement
|
||||||
//~| 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`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:55:20
|
--> $DIR/feature-gate.rs:54:20
|
||||||
|
|
|
|
||||||
LL | #[cfg(FALSE)] (let 0 = 1);
|
LL | #[cfg(FALSE)] (let 0 = 1);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/feature-gate.rs:45:17
|
--> $DIR/feature-gate.rs:45:17
|
||||||
|
|
|
|
||||||
LL | noop_expr!((let 0 = 1));
|
LL | noop_expr!((let 0 = 1));
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: no rules expected the token `let`
|
error: no rules expected the token `let`
|
||||||
--> $DIR/feature-gate.rs:58:15
|
--> $DIR/feature-gate.rs:56:15
|
||||||
|
|
|
|
||||||
LL | macro_rules! use_expr {
|
LL | macro_rules! use_expr {
|
||||||
| --------------------- when calling this macro
|
| --------------------- when calling this macro
|
||||||
|
@ -20,7 +24,7 @@ LL | use_expr!(let 0 = 1);
|
||||||
| ^^^ no rules expected this token in macro call
|
| ^^^ no rules expected this token in macro call
|
||||||
|
|
|
|
||||||
note: while trying to match meta-variable `$e:expr`
|
note: while trying to match meta-variable `$e:expr`
|
||||||
--> $DIR/feature-gate.rs:50:10
|
--> $DIR/feature-gate.rs:49:10
|
||||||
|
|
|
|
||||||
LL | ($e:expr) => {
|
LL | ($e:expr) => {
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
@ -97,24 +101,6 @@ LL | while let Range { start: _, end: _ } = (true..true) && false {}
|
||||||
= 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[E0658]: `let` expressions in this position are unstable
|
error: aborting due to 11 previous errors
|
||||||
--> $DIR/feature-gate.rs:55:20
|
|
||||||
|
|
|
||||||
LL | #[cfg(FALSE)] (let 0 = 1);
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: `let` expressions in this position are unstable
|
|
||||||
--> $DIR/feature-gate.rs:45:17
|
|
||||||
|
|
|
||||||
LL | noop_expr!((let 0 = 1));
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
|
|
||||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 13 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
|
@ -12,6 +12,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
|
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
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
//~| ERROR expected expression, found `let` statement
|
//~| ERROR expected expression, found `let` statement
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -31,6 +32,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
|
if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
|
||||||
//~^ ERROR expected expression, found `let` statement
|
//~^ ERROR expected expression, found `let` statement
|
||||||
|
//~| ERROR expected expression, found `let` statement
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,36 +3,64 @@ error: expected expression, found `let` statement
|
||||||
|
|
|
|
||||||
LL | let _ = &&let Some(x) = Some(42);
|
LL | let _ = &&let Some(x) = Some(42);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:47
|
--> $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 {
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:57
|
--> $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 {
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/invalid-let-in-a-valid-let-context.rs:23:23
|
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:12
|
||||||
|
|
|
||||||
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
|
error: expected expression, found `let` statement
|
||||||
|
--> $DIR/invalid-let-in-a-valid-let-context.rs:24:23
|
||||||
|
|
|
|
||||||
LL | [1, 2, 3][let _ = ()];
|
LL | [1, 2, 3][let _ = ()];
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/invalid-let-in-a-valid-let-context.rs:32:47
|
--> $DIR/invalid-let-in-a-valid-let-context.rs:33:47
|
||||||
|
|
|
|
||||||
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: expected expression, found `let` statement
|
error: expected expression, found `let` statement
|
||||||
--> $DIR/invalid-let-in-a-valid-let-context.rs:40:21
|
--> $DIR/invalid-let-in-a-valid-let-context.rs:33:12
|
||||||
|
|
|
||||||
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
|
error: expected expression, found `let` statement
|
||||||
|
--> $DIR/invalid-let-in-a-valid-let-context.rs:42:21
|
||||||
|
|
|
|
||||||
LL | let x = let y = 1;
|
LL | let x = let y = 1;
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: only supported directly in conditions of `if` and `while` expressions
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue