From db09345ef6e7f39110704e6196bb239d8f10fc27 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:38:43 +0200 Subject: [PATCH] Add suggestions for expressions in patterns --- compiler/rustc_errors/src/lib.rs | 2 + compiler/rustc_parse/messages.ftl | 8 + compiler/rustc_parse/src/errors.rs | 77 +++ compiler/rustc_parse/src/parser/pat.rs | 227 ++++++- compiler/rustc_parse/src/parser/stmt.rs | 10 +- .../range_pat_interactions1.stderr | 11 + .../range_pat_interactions2.stderr | 23 +- tests/ui/parser/issues/issue-24375.stderr | 15 + tests/ui/parser/pat-lt-bracket-6.stderr | 4 +- tests/ui/parser/recover/recover-pat-exprs.rs | 10 +- .../parser/recover/recover-pat-exprs.stderr | 615 ++++++++++++++++-- .../parser/recover/recover-pat-issues.stderr | 75 +++ .../ui/parser/recover/recover-pat-lets.stderr | 20 + .../parser/recover/recover-pat-ranges.stderr | 120 +++- .../recover/recover-pat-wildcards.stderr | 23 +- 15 files changed, 1145 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 094e3010471..59866012069 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -571,6 +571,8 @@ pub enum StashKey { /// Query cycle detected, stashing in favor of a better error. Cycle, UndeterminedMacroResolution, + /// Used by `Parser::maybe_recover_trailing_expr` + ExprInPat, } fn default_track_diagnostic(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 3d0ce77bc47..f5aa8984f51 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -807,6 +807,14 @@ parse_unexpected_expr_in_pat = .label = arbitrary expressions are not allowed in patterns +parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const` + +parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard + +parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`) + +parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard + parse_unexpected_if_with_if = unexpected `if` in the condition expression .suggestion = remove the `if` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index a91aa1f5018..e3e7fcebaaa 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + use std::borrow::Cow; use rustc_ast::token::Token; @@ -2592,11 +2594,86 @@ pub(crate) struct ExpectedCommaAfterPatternField { #[derive(Diagnostic)] #[diag(parse_unexpected_expr_in_pat)] pub(crate) struct UnexpectedExpressionInPattern { + /// The unexpected expr's span. #[primary_span] #[label] pub span: Span, /// Was a `RangePatternBound` expected? pub is_bound: bool, + /// The unexpected expr's precedence (used in match arm guard suggestions). + pub expr_precedence: i8, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnexpectedExpressionInPatternSugg { + #[multipart_suggestion( + parse_unexpected_expr_in_pat_create_guard_sugg, + applicability = "maybe-incorrect" + )] + CreateGuard { + /// Where to put the suggested identifier. + #[suggestion_part(code = "{ident}")] + ident_span: Span, + /// Where to put the match arm. + #[suggestion_part(code = " if {ident} == {expr}")] + pat_hi: Span, + /// The suggested identifier. + ident: String, + /// The unexpected expression. + expr: String, + }, + + #[multipart_suggestion( + parse_unexpected_expr_in_pat_update_guard_sugg, + applicability = "maybe-incorrect" + )] + UpdateGuard { + /// Where to put the suggested identifier. + #[suggestion_part(code = "{ident}")] + ident_span: Span, + /// The beginning of the match arm guard's expression (insert a `(` if `Some`). + #[suggestion_part(code = "(")] + guard_lo: Option, + /// The end of the match arm guard's expression. + #[suggestion_part(code = "{guard_hi_paren} && {ident} == {expr}")] + guard_hi: Span, + /// Either `")"` or `""`. + guard_hi_paren: &'static str, + /// The suggested identifier. + ident: String, + /// The unexpected expression. + expr: String, + }, + + #[multipart_suggestion( + parse_unexpected_expr_in_pat_const_sugg, + applicability = "has-placeholders" + )] + Const { + /// Where to put the extracted constant declaration. + #[suggestion_part(code = "{indentation}const {ident}: /* Type */ = {expr};\n")] + stmt_lo: Span, + /// Where to put the suggested identifier. + #[suggestion_part(code = "{ident}")] + ident_span: Span, + /// The suggested identifier. + ident: String, + /// The unexpected expression. + expr: String, + /// The statement's block's indentation. + indentation: String, + }, + + #[multipart_suggestion( + parse_unexpected_expr_in_pat_inline_const_sugg, + applicability = "maybe-incorrect" + )] + InlineConst { + #[suggestion_part(code = "const {{ ")] + start_span: Span, + #[suggestion_part(code = " }}")] + end_span: Span, + }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 94c01f7e0d4..647df25c82e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,12 +1,14 @@ -use rustc_ast::mut_visit::{walk_pat, MutVisitor}; +use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; +use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField, - PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, + self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, ExprPrecedence, + LocalKind, MacCall, Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, + RangeSyntax, Stmt, StmtKind, }; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diag, PResult}; +use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; @@ -21,8 +23,8 @@ use crate::errors::{ InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, - TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern, - UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, + TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg, + UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; use crate::parser::expr::{could_be_unclosed_char_literal, DestructuredFloat}; @@ -448,12 +450,219 @@ impl<'a> Parser<'a> { || self.token == token::CloseDelim(Delimiter::Parenthesis) && self.look_ahead(1, Token::is_range_separator); + let span = expr.span; + Some(( - self.dcx().emit_err(UnexpectedExpressionInPattern { span: expr.span, is_bound }), - expr.span, + self.dcx() + .create_err(UnexpectedExpressionInPattern { + span, + is_bound, + expr_precedence: expr.precedence().order(), + }) + .stash(span, StashKey::ExprInPat) + .unwrap(), + span, )) } + /// Called by [`Parser::parse_stmt_without_recovery`], used to add statement-aware subdiagnostics to the errors stashed + /// by [`Parser::maybe_recover_trailing_expr`]. + pub(super) fn maybe_augment_stashed_expr_in_pats_with_suggestions(&mut self, stmt: &Stmt) { + if self.dcx().has_errors().is_none() { + // No need to walk the statement if there's no stashed errors. + return; + } + + struct PatVisitor<'a> { + /// `self` + parser: &'a Parser<'a>, + /// The freshly-parsed statement. + stmt: &'a Stmt, + /// The current match arm (for arm guard suggestions). + arm: Option<&'a Arm>, + /// The current struct field (for variable name suggestions). + field: Option<&'a PatField>, + } + + impl<'a> PatVisitor<'a> { + /// Looks for stashed [`StashKey::ExprInPat`] errors in `stash_span`, and emit them with suggestions. + /// `stash_span` is contained in `expr_span`, the latter being larger in borrow patterns; + /// ```txt + /// &mut x.y + /// -----^^^ `stash_span` + /// | + /// `expr_span` + /// ``` + /// `is_range_bound` is used to exclude arm guard suggestions in range pattern bounds. + fn maybe_add_suggestions_then_emit( + &self, + stash_span: Span, + expr_span: Span, + is_range_bound: bool, + ) { + self.parser.dcx().try_steal_modify_and_emit_err( + stash_span, + StashKey::ExprInPat, + |err| { + // Includes pre-pats (e.g. `&mut `) in the diagnostic. + err.span.replace(stash_span, expr_span); + + let sm = self.parser.psess.source_map(); + let stmt = self.stmt; + let line_lo = sm.span_extend_to_line(stmt.span).shrink_to_lo(); + let indentation = sm.indentation_before(stmt.span).unwrap_or_default(); + let Ok(expr) = self.parser.span_to_snippet(expr_span) else { + // FIXME: some suggestions don't actually need the snippet; see PR #123877's unresolved conversations. + return; + }; + + if let StmtKind::Let(local) = &stmt.kind { + match &local.kind { + LocalKind::Decl | LocalKind::Init(_) => { + // It's kinda hard to guess what the user intended, so don't make suggestions. + return; + } + + LocalKind::InitElse(_, _) => {} + } + } + + // help: use an arm guard `if val == expr` + // FIXME(guard_patterns): suggest this regardless of a match arm. + if let Some(arm) = &self.arm + && !is_range_bound + { + let (ident, ident_span) = match self.field { + Some(field) => { + (field.ident.to_string(), field.ident.span.to(expr_span)) + } + None => ("val".to_owned(), expr_span), + }; + + // Are parentheses required around `expr`? + // HACK: a neater way would be preferable. + let expr = match &err.args["expr_precedence"] { + DiagArgValue::Number(expr_precedence) => { + if *expr_precedence + <= ExprPrecedence::Binary(BinOpKind::Eq).order() as i32 + { + format!("({expr})") + } else { + format!("{expr}") + } + } + _ => unreachable!(), + }; + + match &arm.guard { + None => { + err.subdiagnostic( + UnexpectedExpressionInPatternSugg::CreateGuard { + ident_span, + pat_hi: arm.pat.span.shrink_to_hi(), + ident, + expr, + }, + ); + } + Some(guard) => { + // Are parentheses required around the old guard? + let wrap_guard = guard.precedence().order() + <= ExprPrecedence::Binary(BinOpKind::And).order(); + + err.subdiagnostic( + UnexpectedExpressionInPatternSugg::UpdateGuard { + ident_span, + guard_lo: if wrap_guard { + Some(guard.span.shrink_to_lo()) + } else { + None + }, + guard_hi: guard.span.shrink_to_hi(), + guard_hi_paren: if wrap_guard { ")" } else { "" }, + ident, + expr, + }, + ); + } + } + } + + // help: extract the expr into a `const VAL: _ = expr` + let ident = match self.field { + Some(field) => field.ident.as_str().to_uppercase(), + None => "VAL".to_owned(), + }; + err.subdiagnostic(UnexpectedExpressionInPatternSugg::Const { + stmt_lo: line_lo, + ident_span: expr_span, + expr, + ident, + indentation, + }); + + // help: wrap the expr in a `const { expr }` + // FIXME(inline_const_pat): once stabilized, remove this check and remove the `(requires #[feature(inline_const_pat)])` note from the message + if self.parser.psess.unstable_features.is_nightly_build() { + err.subdiagnostic(UnexpectedExpressionInPatternSugg::InlineConst { + start_span: expr_span.shrink_to_lo(), + end_span: expr_span.shrink_to_hi(), + }); + } + }, + ); + } + } + + impl<'a> Visitor<'a> for PatVisitor<'a> { + fn visit_arm(&mut self, a: &'a Arm) -> Self::Result { + self.arm = Some(a); + visit::walk_arm(self, a); + self.arm = None; + } + + fn visit_pat_field(&mut self, fp: &'a PatField) -> Self::Result { + self.field = Some(fp); + visit::walk_pat_field(self, fp); + self.field = None; + } + + fn visit_pat(&mut self, p: &'a Pat) -> Self::Result { + match &p.kind { + // Base expression + PatKind::Err(_) | PatKind::Lit(_) => { + self.maybe_add_suggestions_then_emit(p.span, p.span, false) + } + + // Sub-patterns + // FIXME: this doesn't work with recursive subpats (`&mut &mut `) + PatKind::Box(subpat) | PatKind::Ref(subpat, _) + if matches!(subpat.kind, PatKind::Err(_) | PatKind::Lit(_)) => + { + self.maybe_add_suggestions_then_emit(subpat.span, p.span, false) + } + + // Sub-expressions + PatKind::Range(start, end, _) => { + if let Some(start) = start { + self.maybe_add_suggestions_then_emit(start.span, start.span, true); + } + + if let Some(end) = end { + self.maybe_add_suggestions_then_emit(end.span, end.span, true); + } + } + + // Walk continuation + _ => visit::walk_pat(self, p), + } + } + } + + // Starts the visit. + PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt); + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -845,7 +1054,7 @@ impl<'a> Parser<'a> { self.0 = true; *m = Mutability::Mut; } - walk_pat(self, pat); + mut_visit::walk_pat(self, pat); } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 26ad39e06cd..92fba89d28a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -29,6 +29,9 @@ use crate::{errors, maybe_whole}; impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. + /// + /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of + /// whether or not we have attributes. // Public for rustfmt usage. pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option> { Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| { @@ -66,7 +69,7 @@ impl<'a> Parser<'a> { }); } - Ok(Some(if self.token.is_keyword(kw::Let) { + let stmt = if self.token.is_keyword(kw::Let) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(kw::Let)?; let local = this.parse_local(attrs)?; @@ -163,7 +166,10 @@ impl<'a> Parser<'a> { } else { self.error_outer_attrs(attrs); return Ok(None); - })) + }; + + self.maybe_augment_stashed_expr_in_pats_with_suggestions(&stmt); + Ok(Some(stmt)) } fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index c14021e009b..9831348de75 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -3,6 +3,17 @@ error: expected a pattern range bound, found an expression | LL | 0..5+1 => errors_only.push(x), | ^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 5+1; +LL ~ match x as i32 { +LL ~ 0..VAL => errors_only.push(x), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | 0..const { 5+1 } => errors_only.push(x), + | +++++++ + error[E0408]: variable `n` is not bound in all patterns --> $DIR/range_pat_interactions1.rs:10:25 diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index 136296fa5b0..1b5e875cccb 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -1,9 +1,3 @@ -error: expected a pattern range bound, found an expression - --> $DIR/range_pat_interactions2.rs:10:18 - | -LL | 0..=(5+1) => errors_only.push(x), - | ^^^ arbitrary expressions are not allowed in patterns - error: range pattern bounds cannot have parentheses --> $DIR/range_pat_interactions2.rs:10:17 | @@ -16,6 +10,23 @@ LL - 0..=(5+1) => errors_only.push(x), LL + 0..=5+1 => errors_only.push(x), | +error: expected a pattern range bound, found an expression + --> $DIR/range_pat_interactions2.rs:10:18 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 5+1; +LL ~ match x as i32 { +LL ~ 0..=(VAL) => errors_only.push(x), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | 0..=(const { 5+1 }) => errors_only.push(x), + | +++++++ + + error[E0658]: inline-const in pattern position is experimental --> $DIR/range_pat_interactions2.rs:15:20 | diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index e6ef07d13fd..a25c277d78a 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -3,6 +3,21 @@ error: expected a pattern, found an expression | LL | tmp[0] => {} | ^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == tmp[0] => {} + | ~~~ ++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = tmp[0]; +LL ~ match z { +LL ~ VAL => {} + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { tmp[0] } => {} + | +++++++ + error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr index 10c638a63e4..892883c4aed 100644 --- a/tests/ui/parser/pat-lt-bracket-6.stderr +++ b/tests/ui/parser/pat-lt-bracket-6.stderr @@ -1,8 +1,8 @@ error: expected a pattern, found an expression - --> $DIR/pat-lt-bracket-6.rs:5:15 + --> $DIR/pat-lt-bracket-6.rs:5:14 | LL | let Test(&desc[..]) = x; - | ^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^ arbitrary expressions are not allowed in patterns error[E0308]: mismatched types --> $DIR/pat-lt-bracket-6.rs:10:30 diff --git a/tests/ui/parser/recover/recover-pat-exprs.rs b/tests/ui/parser/recover/recover-pat-exprs.rs index 031e49cb8eb..e5e25df0c01 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.rs +++ b/tests/ui/parser/recover/recover-pat-exprs.rs @@ -53,13 +53,21 @@ fn type_cast() { } } -// ArithmeticOrLogicalExpression +// ArithmeticOrLogicalExpression, also check if parentheses are added as needed fn operator() { match 0 { 1 + 1 => (), //~ error: expected a pattern, found an expression (1 + 2) * 3 => (), //~^ error: expected a pattern, found an expression //~| error: expected a pattern, found an expression + x.0 > 2 => (), //~ error: expected a pattern, found an expression + x.0 == 2 => (), //~ error: expected a pattern, found an expression + } + + // preexisting match arm guard + match (0, 0) { + (x, y.0 > 2) if x != 0 => (), //~ error: expected a pattern, found an expression + (x, y.0 > 2) if x != 0 || x != 1 => (), //~ error: expected a pattern, found an expression } } diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr index ea8d1458d27..63956f35c07 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.stderr +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -3,30 +3,117 @@ error: expected a pattern, found an expression | LL | x.y => (), | ^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.y => (), + | ~~~ +++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.y; +LL ~ match 0 { +LL | x => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.y } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:6:9 | LL | x.0 => (), | ^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.0 => (), + | ~~~ +++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.0; +LL ~ match 0 { +LL | x => (), +LL | x.y => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.0 } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:7:9 | LL | x._0 => (), | ^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x._0 => (), + | ~~~ ++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x._0; +LL ~ match 0 { +LL | x => (), +LL | x.y => (), +LL | x.0 => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x._0 } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:8:9 | LL | x.0.1 => (), | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.0.1 => (), + | ~~~ +++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.0.1; +LL ~ match 0 { +LL | x => (), +... +LL | x._0 => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.0.1 } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:9:9 | LL | x.4.y.17.__z => (), | ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.4.y.17.__z => (), + | ~~~ ++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.4.y.17.__z; +LL ~ match 0 { +LL | x => (), +... +LL | x.0.1 => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.4.y.17.__z } => (), + | +++++++ + error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.` --> $DIR/recover-pat-exprs.rs:12:12 @@ -63,12 +150,43 @@ error: expected a pattern, found an expression | LL | x[0] => (), | ^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x[0] => (), + | ~~~ ++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x[0]; +LL ~ match 0 { +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x[0] } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:24:9 | LL | x[..] => (), | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x[..] => (), + | ~~~ +++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x[..]; +LL ~ match 0 { +LL | x[0] => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x[..] } => (), + | +++++++ + error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` --> $DIR/recover-pat-exprs.rs:27:12 @@ -102,99 +220,365 @@ error: expected a pattern, found an expression | LL | x.f() => (), | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.f() => (), + | ~~~ +++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.f(); +LL ~ match 0 { +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.f() } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:38:9 | LL | x._f() => (), | ^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x._f() => (), + | ~~~ ++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x._f(); +LL ~ match 0 { +LL | x.f() => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x._f() } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:39:9 | LL | x? => (), | ^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x? => (), + | ~~~ ++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x?; +LL ~ match 0 { +LL | x.f() => (), +LL | x._f() => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x? } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:40:9 | LL | ().f() => (), | ^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == ().f() => (), + | ~~~ ++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = ().f(); +LL ~ match 0 { +LL | x.f() => (), +LL | x._f() => (), +LL | x? => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { ().f() } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:41:9 | LL | (0, x)?.f() => (), | ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == (0, x)?.f() => (), + | ~~~ +++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = (0, x)?.f(); +LL ~ match 0 { +LL | x.f() => (), +... +LL | ().f() => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { (0, x)?.f() } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:42:9 | LL | x.f().g() => (), | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.f().g() => (), + | ~~~ +++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.f().g(); +LL ~ match 0 { +LL | x.f() => (), +... +LL | (0, x)?.f() => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.f().g() } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:43:9 | LL | 0.f()?.g()?? => (), | ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == 0.f()?.g()?? => (), + | ~~~ ++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 0.f()?.g()??; +LL ~ match 0 { +LL | x.f() => (), +... +LL | x.f().g() => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { 0.f()?.g()?? } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:50:9 | LL | x as usize => (), | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x as usize => (), + | ~~~ ++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x as usize; +LL ~ match 0 { +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x as usize } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:51:9 | LL | 0 as usize => (), | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == 0 as usize => (), + | ~~~ ++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 0 as usize; +LL ~ match 0 { +LL | x as usize => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { 0 as usize } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:52:9 | LL | x.f().0.4 as f32 => (), | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == x.f().0.4 as f32 => (), + | ~~~ ++++++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.f().0.4 as f32; +LL ~ match 0 { +LL | x as usize => (), +LL | 0 as usize => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.f().0.4 as f32 } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:59:9 | LL | 1 + 1 => (), | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:60:10 | -LL | (1 + 2) * 3 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns +help: consider moving the expression to a match arm guard + | +LL | val if val == 1 + 1 => (), + | ~~~ +++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 1 + 1; +LL ~ match 0 { +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { 1 + 1 } => (), + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:60:9 | LL | (1 + 2) * 3 => (), | ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == (1 + 2) * 3 => (), + | ~~~ +++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = (1 + 2) * 3; +LL ~ match 0 { +LL | 1 + 1 => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { (1 + 2) * 3 } => (), + | +++++++ + error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:67:5 + --> $DIR/recover-pat-exprs.rs:63:9 | -LL | 1 + 2 * PI.cos() => 2, - | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns +LL | x.0 > 2 => (), + | ^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == (x.0 > 2) => (), + | ~~~ +++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.0 > 2; +LL ~ match 0 { +LL | 1 + 1 => (), +... +LL | +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.0 > 2 } => (), + | +++++++ + error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:73:9 + --> $DIR/recover-pat-exprs.rs:64:9 | -LL | u8::MAX.abs() => (), - | ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:75:9 - | -LL | x.sqrt() @ .. => (), +LL | x.0 == 2 => (), | ^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == (x.0 == 2) => (), + | ~~~ ++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = x.0 == 2; +LL ~ match 0 { +LL | 1 + 1 => (), +... +LL | x.0 > 2 => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { x.0 == 2 } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:69:13 + | +LL | (x, y.0 > 2) if x != 0 => (), + | ^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to the match arm guard + | +LL | (x, val) if x != 0 && val == (y.0 > 2) => (), + | ~~~ +++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = y.0 > 2; +LL ~ match (0, 0) { +LL ~ (x, VAL) if x != 0 => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | (x, const { y.0 > 2 }) if x != 0 => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:70:13 + | +LL | (x, y.0 > 2) if x != 0 || x != 1 => (), + | ^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to the match arm guard + | +LL | (x, val) if (x != 0 || x != 1) && val == (y.0 > 2) => (), + | ~~~ + +++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = y.0 > 2; +LL ~ match (0, 0) { +LL | (x, y.0 > 2) if x != 0 => (), +LL ~ (x, VAL) if x != 0 || x != 1 => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | (x, const { y.0 > 2 }) if x != 0 || x != 1 => (), + | +++++++ + error: left-hand side of `@` must be a binding - --> $DIR/recover-pat-exprs.rs:75:9 + --> $DIR/recover-pat-exprs.rs:83:9 | LL | x.sqrt() @ .. => (), | --------^^^-- @@ -204,50 +588,161 @@ LL | x.sqrt() @ .. => (), | = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:78:17 - | -LL | z @ w @ v.u() => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:80:9 - | -LL | y.ilog(3) => (), - | ^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:82:9 - | -LL | n + 1 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:84:10 - | -LL | ("".f() + 14 * 8) => (), - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:87:9 - | -LL | f?() => (), - | ^^^^ arbitrary expressions are not allowed in patterns - error: expected one of `)`, `,`, or `|`, found `+` - --> $DIR/recover-pat-exprs.rs:89:12 + --> $DIR/recover-pat-exprs.rs:97:12 | LL | (_ + 1) => (), | ^ expected one of `)`, `,`, or `|` error: expected a pattern, found an expression - --> $DIR/recover-pat-exprs.rs:93:9 + --> $DIR/recover-pat-exprs.rs:81:9 + | +LL | u8::MAX.abs() => (), + | ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == u8::MAX.abs() => (), + | ~~~ +++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = u8::MAX.abs(); +LL ~ match u8::MAX { +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { u8::MAX.abs() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:86:17 + | +LL | z @ w @ v.u() => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | z @ w @ val if val == v.u() => (), + | ~~~ +++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = v.u(); +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), +... +LL | +LL ~ z @ w @ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | z @ w @ const { v.u() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:88:9 + | +LL | y.ilog(3) => (), + | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == y.ilog(3) => (), + | ~~~ +++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = y.ilog(3); +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), +... +LL | +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { y.ilog(3) } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:90:9 + | +LL | n + 1 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == n + 1 => (), + | ~~~ +++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = n + 1; +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), +... +LL | +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { n + 1 } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:92:10 + | +LL | ("".f() + 14 * 8) => (), + | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | (val) if val == "".f() + 14 * 8 => (), + | ~~~ +++++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = "".f() + 14 * 8; +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), +... +LL | +LL ~ (VAL) => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | (const { "".f() + 14 * 8 }) => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:95:9 + | +LL | f?() => (), + | ^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | val if val == f?() => (), + | ~~~ ++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = f?(); +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), +... +LL | 0 | ((1) | 2) | 3 => (), +LL ~ VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { f?() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:101:9 | LL | let 1 + 1 = 2; | ^^^^^ arbitrary expressions are not allowed in patterns error: expected one of `)`, `,`, `@`, or `|`, found `*` - --> $DIR/recover-pat-exprs.rs:96:28 + --> $DIR/recover-pat-exprs.rs:104:28 | LL | let b = matches!(x, (x * x | x.f()) | x[0]); | ^ expected one of `)`, `,`, `@`, or `|` @@ -255,5 +750,23 @@ LL | let b = matches!(x, (x * x | x.f()) | x[0]); | = note: while parsing argument for this `pat` macro fragment -error: aborting due to 41 previous errors +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:60:10 + | +LL | (1 + 2) * 3 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:75:5 + | +LL | 1 + 2 * PI.cos() => 2, + | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:83:9 + | +LL | x.sqrt() @ .. => (), + | ^^^^^^^^ arbitrary expressions are not allowed in patterns + +error: aborting due to 45 previous errors diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr index 793091bb1f1..596bff21395 100644 --- a/tests/ui/parser/recover/recover-pat-issues.stderr +++ b/tests/ui/parser/recover/recover-pat-issues.stderr @@ -3,36 +3,111 @@ error: expected a pattern, found an expression | LL | Foo("hi".to_owned()) => true, | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | Foo(val) if val == "hi".to_owned() => true, + | ~~~ +++++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = "hi".to_owned(); +LL ~ match foo { +LL ~ Foo(VAL) => true, + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | Foo(const { "hi".to_owned() }) => true, + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:14:20 | LL | Bar { baz: "hi".to_owned() } => true, | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | Bar { baz } if baz == "hi".to_owned() => true, + | ~~~ +++++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const BAZ: /* Type */ = "hi".to_owned(); +LL ~ match bar { +LL ~ Bar { baz: BAZ } => true, + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | Bar { baz: const { "hi".to_owned() } } => true, + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:25:11 | LL | &["foo".to_string()] => {} | ^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider moving the expression to a match arm guard + | +LL | &[val] if val == "foo".to_string() => {} + | ~~~ +++++++++++++++++++++++++++ +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = "foo".to_string(); +LL ~ match foo.as_slice() { +LL ~ &[VAL] => {} + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | &[const { "foo".to_string() }] => {} + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:36:17 | LL | if let Some(MAGIC.0 as usize) = None:: {} | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = MAGIC.0 as usize; +LL ~ if let Some(VAL) = None:: {} + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | if let Some(const { MAGIC.0 as usize }) = None:: {} + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:41:13 | LL | if let (-1.some(4)) = (0, Some(4)) {} | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = -1.some(4); +LL ~ if let (VAL) = (0, Some(4)) {} + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | if let (const { -1.some(4) }) = (0, Some(4)) {} + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:44:13 | LL | if let (-1.Some(4)) = (0, Some(4)) {} | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = -1.Some(4); +LL ~ if let (VAL) = (0, Some(4)) {} + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | if let (const { -1.Some(4) }) = (0, Some(4)) {} + | +++++++ + error: aborting due to 6 previous errors diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr index b1d2a9b96d9..e54586b0924 100644 --- a/tests/ui/parser/recover/recover-pat-lets.stderr +++ b/tests/ui/parser/recover/recover-pat-lets.stderr @@ -21,12 +21,32 @@ error: expected a pattern, found an expression | LL | let Some(1 + 1) = x else { | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 1 + 1; +LL ~ let Some(VAL) = x else { + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | let Some(const { 1 + 1 }) = x else { + | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:17:17 | LL | if let Some(1 + 1) = x { | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 1 + 1; +LL ~ if let Some(VAL) = x { + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | if let Some(const { 1 + 1 }) = x { + | +++++++ + error: aborting due to 5 previous errors diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr index 62ef7a8a908..088f83b0ccb 100644 --- a/tests/ui/parser/recover/recover-pat-ranges.stderr +++ b/tests/ui/parser/recover/recover-pat-ranges.stderr @@ -46,12 +46,6 @@ LL - (0)..=(-4) => (), LL + (0)..=-4 => (), | -error: expected a pattern range bound, found an expression - --> $DIR/recover-pat-ranges.rs:11:12 - | -LL | ..=1 + 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - error: range pattern bounds cannot have parentheses --> $DIR/recover-pat-ranges.rs:13:9 | @@ -64,12 +58,6 @@ LL - (4).. => (), LL + 4.. => (), | -error: expected a pattern range bound, found an expression - --> $DIR/recover-pat-ranges.rs:15:10 - | -LL | (-4 + 0).. => (), - | ^^^^^^ arbitrary expressions are not allowed in patterns - error: range pattern bounds cannot have parentheses --> $DIR/recover-pat-ranges.rs:15:9 | @@ -82,12 +70,6 @@ LL - (-4 + 0).. => (), LL + -4 + 0.. => (), | -error: expected a pattern range bound, found an expression - --> $DIR/recover-pat-ranges.rs:18:10 - | -LL | (1 + 4)...1 * 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - error: range pattern bounds cannot have parentheses --> $DIR/recover-pat-ranges.rs:18:9 | @@ -100,23 +82,125 @@ LL - (1 + 4)...1 * 2 => (), LL + 1 + 4...1 * 2 => (), | +error: expected a pattern range bound, found an expression + --> $DIR/recover-pat-ranges.rs:11:12 + | +LL | ..=1 + 2 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 1 + 2; +LL ~ match -1 { +LL | 0..=1 => (), +... +LL | +LL ~ ..=VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | ..=const { 1 + 2 } => (), + | +++++++ + + +error: expected a pattern range bound, found an expression + --> $DIR/recover-pat-ranges.rs:15:10 + | +LL | (-4 + 0).. => (), + | ^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = -4 + 0; +LL ~ match -1 { +LL | 0..=1 => (), +... +LL | +LL ~ (VAL).. => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | (const { -4 + 0 }).. => (), + | +++++++ + + +error: expected a pattern range bound, found an expression + --> $DIR/recover-pat-ranges.rs:18:10 + | +LL | (1 + 4)...1 * 2 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 1 + 4; +LL ~ match -1 { +LL | 0..=1 => (), +... +LL | +LL ~ (VAL)...1 * 2 => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | (const { 1 + 4 })...1 * 2 => (), + | +++++++ + + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:18:19 | LL | (1 + 4)...1 * 2 => (), | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 1 * 2; +LL ~ match -1 { +LL | 0..=1 => (), +... +LL | +LL ~ (1 + 4)...VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | (1 + 4)...const { 1 * 2 } => (), + | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:24:9 | LL | 0.x()..="y".z() => (), | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 0.x(); +LL ~ match -1 { +LL | 0..=1 => (), +... +LL | +LL ~ VAL..="y".z() => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | const { 0.x() }..="y".z() => (), + | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:24:17 | LL | 0.x()..="y".z() => (), | ^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = "y".z(); +LL ~ match -1 { +LL | 0..=1 => (), +... +LL | +LL ~ 0.x()..=VAL => (), + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | 0.x()..=const { "y".z() } => (), + | +++++++ + warning: `...` range patterns are deprecated --> $DIR/recover-pat-ranges.rs:18:16 diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr index 64d477fdeb2..30307726a97 100644 --- a/tests/ui/parser/recover/recover-pat-wildcards.stderr +++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr @@ -59,12 +59,6 @@ error: expected one of `=>`, `if`, or `|`, found `(` LL | ..(_) => () | ^ expected one of `=>`, `if`, or `|` -error: expected a pattern range bound, found an expression - --> $DIR/recover-pat-wildcards.rs:55:14 - | -LL | 4..=(2 + _) => () - | ^^^^^ arbitrary expressions are not allowed in patterns - error: range pattern bounds cannot have parentheses --> $DIR/recover-pat-wildcards.rs:55:13 | @@ -77,6 +71,23 @@ LL - 4..=(2 + _) => () LL + 4..=2 + _ => () | +error: expected a pattern range bound, found an expression + --> $DIR/recover-pat-wildcards.rs:55:14 + | +LL | 4..=(2 + _) => () + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: consider extracting the expression into a `const` + | +LL + const VAL: /* Type */ = 2 + _; +LL ~ match 9 { +LL ~ 4..=(VAL) => () + | +help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) + | +LL | 4..=(const { 2 + _ }) => () + | +++++++ + + error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0586`.