diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index adbac80d7ccb5..7478f9bf0345f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -522,6 +522,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 { @@ -806,6 +808,23 @@ impl DiagCtxt { Some(Diag::new_diagnostic(self, diag)) } + /// Steals a previously stashed error with the given `Span` and + /// [`StashKey`] as the key, and cancels it if found. + /// Panics if the found diagnostic's level isn't `Level::Error`. + pub fn steal_err(&self, span: Span, key: StashKey, _: ErrorGuaranteed) -> bool { + let key = (span.with_parent(None), key); + // FIXME(#120456) - is `swap_remove` correct? + self.inner + .borrow_mut() + .stashed_diagnostics + .swap_remove(&key) + .inspect(|(diag, guar)| { + assert_eq!(diag.level, Error); + assert!(guar.is_some()) + }) + .is_some() + } + /// Steals a previously stashed error with the given `Span` and /// [`StashKey`] as the key, modifies it, and emits it. Returns `None` if /// no matching diagnostic is found. Panics if the found diagnostic's level @@ -1250,6 +1269,17 @@ impl DiagCtxt { self.create_err(err).emit() } + /// See [`DiagCtxt::stash_diagnostic`] for details. + #[track_caller] + pub fn stash_err<'a>( + &'a self, + span: Span, + key: StashKey, + err: impl Diagnostic<'a>, + ) -> ErrorGuaranteed { + self.create_err(err).stash(span, key).unwrap() + } + /// Ensures that an error is printed. See `Level::DelayedBug`. // // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index ea0654572ba95..da256baf00a12 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -780,6 +780,14 @@ parse_unexpected_expr_in_pat = .label = arbitrary expressions are not allowed in patterns +parse_unexpected_expr_in_pat_const_sugg = extract the expression into a `const` and refer to it + +parse_unexpected_expr_in_pat_create_guard_sugg = check the value in an arm guard + +parse_unexpected_expr_in_pat_inline_const_sugg = wrap the expression in a inline const (requires `{"#"}![feature(inline_const)]`) + +parse_unexpected_expr_in_pat_update_guard_sugg = check the value in the 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 e289b2c407b31..ac1f369769b35 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2441,6 +2441,74 @@ pub(crate) struct UnexpectedExpressionInPattern { pub is_bound: bool, } +#[derive(Subdiagnostic)] +pub(crate) enum UnexpectedExpressionInPatternArmSugg { + #[multipart_suggestion( + parse_unexpected_expr_in_pat_create_guard_sugg, + applicability = "maybe-incorrect" + )] + CreateGuard { + /// The span of the `PatKind:Err` to be transformed into a `PatKind::Ident`. + #[suggestion_part(code = "{ident}")] + ident_span: Span, + /// The end of the match arm's pattern. + #[suggestion_part(code = " if {ident} == {expr}")] + pat_hi: Span, + /// The suggested identifier. + ident: String, + /// `ident_span`'s snippet. + expr: String, + }, + #[multipart_suggestion( + parse_unexpected_expr_in_pat_update_guard_sugg, + applicability = "maybe-incorrect" + )] + UpdateGuard { + /// The span of the `PatKind:Err` to be transformed into a `PatKind::Ident`. + #[suggestion_part(code = "{ident}")] + ident_span: Span, + /// The beginning of the match arm guard's expression. + #[suggestion_part(code = "(")] + guard_lo: Span, + /// The end of the match arm guard's expression. + #[suggestion_part(code = ") && {ident} == {expr}")] + guard_hi: Span, + /// The suggested identifier. + ident: String, + /// `ident_span`'s snippet. + expr: String, + }, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_unexpected_expr_in_pat_const_sugg, applicability = "has-placeholders")] +pub(crate) struct UnexpectedExpressionInPatternConstSugg { + /// The beginning of statement's line. + #[suggestion_part(code = "{indentation}const {ident}: _ = {expr};\n")] + pub stmt_lo: Span, + /// The span of the `PatKind:Err` to be transformed into a `PatKind::Ident`. + #[suggestion_part(code = "{ident}")] + pub ident_span: Span, + /// The suggested identifier. + pub ident: String, + /// `ident_span`'s snippet. + pub expr: String, + /// The statement's block's indentation. + pub indentation: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + parse_unexpected_expr_in_pat_inline_const_sugg, + applicability = "maybe-incorrect" +)] +pub(crate) struct UnexpectedExpressionInPatternInlineConstSugg { + #[suggestion_part(code = "const {{ ")] + pub start_span: Span, + #[suggestion_part(code = " }}")] + pub end_span: Span, +} + #[derive(Diagnostic)] #[diag(parse_unexpected_paren_in_range_pat)] pub(crate) struct UnexpectedParenInRangePat { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ed51710564a42..f27d80ae69a69 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -4,7 +4,10 @@ use super::{ AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Recovered, Trailing, TrailingToken, }; -use crate::errors::{self, MacroExpandsToAdtField}; +use crate::errors::{ + self, MacroExpandsToAdtField, UnexpectedExpressionInPatternArmSugg, + UnexpectedExpressionInPatternConstSugg, UnexpectedExpressionInPatternInlineConstSugg, +}; use crate::fluent_generated as fluent; use crate::maybe_whole; use ast::token::IdentIsRaw; @@ -13,6 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; +use rustc_ast::visit::{walk_arm, walk_pat, walk_pat_field, walk_stmt, Visitor}; use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; use rustc_errors::{codes::*, struct_span_code_err, Applicability, PResult, StashKey}; @@ -2362,6 +2366,168 @@ impl<'a> Parser<'a> { } (AttrVec::new(), None) }; + + if let Some(body) = &body + && self.dcx().err_count() > 0 + { + // WIP: once a fn body has been parsed, we walk through all its patterns, + // and emit now what errors `maybe_recover_trailing_expr()` stashed, + // with suggestions depending on which statement the pattern is. + + struct PatVisitor<'a> { + /// `self` + parser: &'a Parser<'a>, + /// The current statement. + stmt: Option<&'a Stmt>, + /// The current match arm. + arm: Option<&'a Arm>, + /// The current struct field. + field: Option<&'a PatField>, + } + + impl<'a> Visitor<'a> for PatVisitor<'a> { + fn visit_stmt(&mut self, s: &'a Stmt) -> Self::Result { + self.stmt = Some(s); + + walk_stmt(self, s) + } + + fn visit_arm(&mut self, a: &'a Arm) -> Self::Result { + self.arm = Some(a); + walk_arm(self, a); + self.arm = None; + } + + fn visit_pat_field(&mut self, fp: &'a PatField) -> Self::Result { + self.field = Some(fp); + walk_pat_field(self, fp); + self.field = None; + } + + fn visit_pat(&mut self, p: &'a Pat) -> Self::Result { + // Looks for stashed `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` + // ``` + let emit_now = |that: &Self, + stash_span: Span, + expr_span: Span| + -> Self::Result { + that.parser.dcx().try_steal_modify_and_emit_err( + stash_span, + StashKey::ExprInPat, + |err| { + let sm = that.parser.psess.source_map(); + let stmt = that.stmt.unwrap(); + let line_lo = sm.span_extend_to_line(stmt.span).shrink_to_lo(); + let indentation = + sm.indentation_before(stmt.span).unwrap_or_default(); + let expr = that.parser.span_to_snippet(expr_span).unwrap(); + + err.span.replace(stash_span, expr_span); + + if let StmtKind::Let(local) = &stmt.kind { + // If we have an `ExprInPat`, the user tried to assign a value to another value, + // which doesn't makes much sense. + match &local.kind { + LocalKind::Decl => {} + LocalKind::Init(_) => {} + LocalKind::InitElse(_, _) => {} + } + } + else { + // help: use an arm guard `if val == expr` + if let Some(arm) = &self.arm { + 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), + }; + + match &arm.guard { + None => { + err.subdiagnostic(&that.parser.dcx(), UnexpectedExpressionInPatternArmSugg::CreateGuard { + ident_span, + pat_hi: arm.pat.span.shrink_to_hi(), + ident, + expr: expr.clone(), + }); + } + Some(guard) => { + err.subdiagnostic(&that.parser.dcx(), UnexpectedExpressionInPatternArmSugg::UpdateGuard { + ident_span, + guard_lo: guard.span.shrink_to_lo(), + guard_hi: guard.span.shrink_to_hi(), + ident, + expr: expr.clone(), + }); + } + } + } + + // 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( + &that.parser.dcx(), + UnexpectedExpressionInPatternConstSugg { + stmt_lo: line_lo, + ident_span: expr_span, + expr, + ident, + indentation, + }, + ); + + // help: wrap the expr in a `const { expr }` + // FIXME(inline_const): once stabilized, remove this check and remove the `(requires #[feature(inline_const])` note from the message + if that.parser.psess.unstable_features.is_nightly_build() { + err.subdiagnostic( + &that.parser.dcx(), + UnexpectedExpressionInPatternInlineConstSugg { + start_span: expr_span.shrink_to_lo(), + end_span: expr_span.shrink_to_hi(), + }, + ); + } + } + }, + ); + }; // end of `emit_now` closure, we're back in `visit_pat` + + match &p.kind { + // Base expression + PatKind::Err(_) => emit_now(self, p.span, p.span), + // Sub-patterns + PatKind::Box(subpat) | PatKind::Ref(subpat, _) + if matches!(subpat.kind, PatKind::Err(_)) => + { + emit_now(self, subpat.span, p.span) + } + // Sub-expressions + PatKind::Range(start, end, _) => { + if let Some(start) = start { + emit_now(self, start.span, start.span); + } + + if let Some(end) = end { + emit_now(self, end.span, end.span); + } + } + // Walk continuation + _ => walk_pat(self, p), + } + } + } // end of `PatVisitor` impl, we're back in `parse_fn_body` + + PatVisitor { parser: self, stmt: None, arm: None, field: None }.visit_block(body); + } + attrs.extend(inner_attrs); Ok(body) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bbd97f211c31c..2b56ea778a294 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -20,7 +20,7 @@ use rustc_ast::{ PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diag, PResult}; +use rustc_errors::{Applicability, Diag, PResult, StashKey}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; @@ -423,10 +423,15 @@ impl<'a> Parser<'a> { || self.token.kind == token::CloseDelim(Delimiter::Parenthesis) && self.look_ahead(1, Token::is_range_separator); + let span = expr.span; + return Some(( - self.dcx() - .emit_err(UnexpectedExpressionInPattern { span: expr.span, is_bound }), - expr.span, + self.dcx().stash_err( + span, + StashKey::ExprInPat, + UnexpectedExpressionInPattern { span, is_bound }, + ), + span, )); } } @@ -584,7 +589,11 @@ impl<'a> Parser<'a> { match self.parse_range_end() { Some(form) => self.parse_pat_range_begin_with(begin, form)?, - None => PatKind::Lit(begin), + None => match &begin.kind { + // Avoid `PatKind::Lit(ExprKind::Err)` + ExprKind::Err(guar) => PatKind::Err(*guar), + _ => PatKind::Lit(begin), + }, } } Err(err) => return self.fatal_unexpected_non_pat(err, expected), @@ -756,7 +765,25 @@ impl<'a> Parser<'a> { Ok(match self.maybe_recover_trailing_expr(open_paren.to(self.prev_token.span), false) { None => pat, - Some((guar, _)) => PatKind::Err(guar), + Some((guar, _)) => { + // We just recovered a bigger expression, so cancel its children + // (e.g. `(1 + 2) * 3`, cancel “`1 + 2` is not a pattern”). + match pat { + PatKind::Paren(pat) => { + self.dcx().steal_err(pat.span, StashKey::ExprInPat, guar); + } + + PatKind::Tuple(fields) => { + for pat in fields { + self.dcx().steal_err(pat.span, StashKey::ExprInPat, guar); + } + } + + _ => unreachable!(), + } + + PatKind::Err(guar) + } }) } 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 cc481f7a79e13..625cc39c90ed1 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,21 @@ 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: check the value in an arm guard + | +LL | 0..val if val == 5+1 => errors_only.push(x), + | ~~~ +++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 5+1; +LL ~ match x as i32 { +LL ~ 0..VAL => errors_only.push(x), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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 8f21a6149fb89..f8444cbbdf6ac 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,27 @@ 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: check the value in an arm guard + | +LL | 0..=(val) if val == 5+1 => errors_only.push(x), + | ~~~ +++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 5+1; +LL ~ match x as i32 { +LL ~ 0..=(VAL) => errors_only.push(x), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | 0..=(const { 5+1 }) => errors_only.push(x), + | +++++++ + + error[E0658]: inline-const in pattern position is experimental --> $DIR/range_pat_interactions2.rs:17:20 | diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr index 44f6c6c620ce5..f859de6478d1f 100644 --- a/tests/ui/parser/bad-name.stderr +++ b/tests/ui/parser/bad-name.stderr @@ -4,17 +4,17 @@ error: field expressions cannot have generic arguments LL | let x.y::.z foo; | ^^^^^^^ -error: expected a pattern, found an expression - --> $DIR/bad-name.rs:4:7 - | -LL | let x.y::.z foo; - | ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo` --> $DIR/bad-name.rs:4:22 | LL | let x.y::.z foo; | ^^^ expected one of 9 possible tokens +error: expected a pattern, found an expression + --> $DIR/bad-name.rs:4:7 + | +LL | let x.y::.z foo; + | ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + error: aborting due to 3 previous errors diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index e6ef07d13fd8d..25c81d62ebc3f 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: check the value in an arm guard + | +LL | val if val == tmp[0] => {} + | ~~~ ++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = tmp[0]; +LL ~ match z { +LL ~ VAL => {} + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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 10c638a63e44c..892883c4aedca 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/pat-recover-exprs.rs b/tests/ui/parser/pat-recover-exprs.rs deleted file mode 100644 index c316148513cf4..0000000000000 --- a/tests/ui/parser/pat-recover-exprs.rs +++ /dev/null @@ -1,28 +0,0 @@ -fn main() { - match u8::MAX { - u8::MAX.abs() => (), - //~^ error: expected a pattern, found an expression - x.sqrt() @ .. => (), - //~^ error: expected a pattern, found an expression - //~| error: left-hand side of `@` must be a binding - z @ w @ v.u() => (), - //~^ error: expected a pattern, found an expression - y.ilog(3) => (), - //~^ error: expected a pattern, found an expression - n + 1 => (), - //~^ error: expected a pattern, found an expression - ("".f() + 14 * 8) => (), - //~^ error: expected a pattern, found an expression - 0 | ((1) | 2) | 3 => (), - f?() => (), - //~^ error: expected a pattern, found an expression - (_ + 1) => (), - //~^ error: expected one of `)`, `,`, or `|`, found `+` - } - - let 1 + 1 = 2; - //~^ error: expected a pattern, found an expression - - let b = matches!(x, (x * x | x.f()) | x[0]); - //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*` -} diff --git a/tests/ui/parser/pat-recover-exprs.stderr b/tests/ui/parser/pat-recover-exprs.stderr deleted file mode 100644 index ffdb78f3f2ecb..0000000000000 --- a/tests/ui/parser/pat-recover-exprs.stderr +++ /dev/null @@ -1,76 +0,0 @@ -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:3:9 - | -LL | u8::MAX.abs() => (), - | ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:5:9 - | -LL | x.sqrt() @ .. => (), - | ^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: left-hand side of `@` must be a binding - --> $DIR/pat-recover-exprs.rs:5:9 - | -LL | x.sqrt() @ .. => (), - | --------^^^-- - | | | - | | also a pattern - | interpreted as a pattern, not a binding - | - = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:8:17 - | -LL | z @ w @ v.u() => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:10:9 - | -LL | y.ilog(3) => (), - | ^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:12:9 - | -LL | n + 1 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:14:10 - | -LL | ("".f() + 14 * 8) => (), - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:17:9 - | -LL | f?() => (), - | ^^^^ arbitrary expressions are not allowed in patterns - -error: expected one of `)`, `,`, or `|`, found `+` - --> $DIR/pat-recover-exprs.rs:19:12 - | -LL | (_ + 1) => (), - | ^ expected one of `)`, `,`, or `|` - -error: expected a pattern, found an expression - --> $DIR/pat-recover-exprs.rs:23:9 - | -LL | let 1 + 1 = 2; - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected one of `)`, `,`, `@`, or `|`, found `*` - --> $DIR/pat-recover-exprs.rs:26:28 - | -LL | let b = matches!(x, (x * x | x.f()) | x[0]); - | ^ expected one of `)`, `,`, `@`, or `|` - --> $SRC_DIR/core/src/macros/mod.rs:LL:COL - | - = note: while parsing argument for this `pat` macro fragment - -error: aborting due to 11 previous errors - diff --git a/tests/ui/parser/pat-recover-methodcalls.stderr b/tests/ui/parser/pat-recover-methodcalls.stderr deleted file mode 100644 index 489b129b0d407..0000000000000 --- a/tests/ui/parser/pat-recover-methodcalls.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: expected a pattern, found an expression - --> $DIR/pat-recover-methodcalls.rs:6:13 - | -LL | Foo("hi".to_owned()) => true, - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-methodcalls.rs:14:20 - | -LL | Bar { baz: "hi".to_owned() } => true, - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-methodcalls.rs:24:11 - | -LL | &["foo".to_string()] => {} - | ^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-methodcalls.rs:31:13 - | -LL | if let (-1.some(4)) = (0, Some(4)) {} - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern, found an expression - --> $DIR/pat-recover-methodcalls.rs:34:13 - | -LL | if let (-1.Some(4)) = (0, Some(4)) {} - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns - -error: aborting due to 5 previous errors - diff --git a/tests/ui/parser/pat-recover-ranges.stderr b/tests/ui/parser/pat-recover-ranges.stderr deleted file mode 100644 index fb7119542f144..0000000000000 --- a/tests/ui/parser/pat-recover-ranges.stderr +++ /dev/null @@ -1,132 +0,0 @@ -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:4:13 - | -LL | 0..=(1) => (), - | ^ ^ - | -help: remove these parentheses - | -LL - 0..=(1) => (), -LL + 0..=1 => (), - | - -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:6:9 - | -LL | (-12)..=4 => (), - | ^ ^ - | -help: remove these parentheses - | -LL - (-12)..=4 => (), -LL + -12..=4 => (), - | - -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:8:9 - | -LL | (0)..=(-4) => (), - | ^ ^ - | -help: remove these parentheses - | -LL - (0)..=(-4) => (), -LL + 0..=(-4) => (), - | - -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:8:15 - | -LL | (0)..=(-4) => (), - | ^ ^ - | -help: remove these parentheses - | -LL - (0)..=(-4) => (), -LL + (0)..=-4 => (), - | - -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-ranges.rs:11:12 - | -LL | ..=1 + 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:13:9 - | -LL | (4).. => (), - | ^ ^ - | -help: remove these parentheses - | -LL - (4).. => (), -LL + 4.. => (), - | - -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-ranges.rs:15:10 - | -LL | (-4 + 0).. => (), - | ^^^^^^ arbitrary expressions are not allowed in patterns - -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:15:9 - | -LL | (-4 + 0).. => (), - | ^ ^ - | -help: remove these parentheses - | -LL - (-4 + 0).. => (), -LL + -4 + 0.. => (), - | - -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-ranges.rs:18:10 - | -LL | (1 + 4)...1 * 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-ranges.rs:18:9 - | -LL | (1 + 4)...1 * 2 => (), - | ^ ^ - | -help: remove these parentheses - | -LL - (1 + 4)...1 * 2 => (), -LL + 1 + 4...1 * 2 => (), - | - -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-ranges.rs:18:19 - | -LL | (1 + 4)...1 * 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-ranges.rs:24:9 - | -LL | 0.x()..="y".z() => (), - | ^^^^^ arbitrary expressions are not allowed in patterns - -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-ranges.rs:24:17 - | -LL | 0.x()..="y".z() => (), - | ^^^^^^^ arbitrary expressions are not allowed in patterns - -warning: `...` range patterns are deprecated - --> $DIR/pat-recover-ranges.rs:18:16 - | -LL | (1 + 4)...1 * 2 => (), - | ^^^ help: use `..=` for an inclusive range - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default - -error: aborting due to 13 previous errors; 1 warning emitted - diff --git a/tests/ui/parser/recover/recover-pat-exprs.rs b/tests/ui/parser/recover/recover-pat-exprs.rs new file mode 100644 index 0000000000000..3a54649387d54 --- /dev/null +++ b/tests/ui/parser/recover/recover-pat-exprs.rs @@ -0,0 +1,71 @@ +// FieldExpression, TupleIndexingExpression +fn field_access() { + match 0 { + x => (), + x.y => (), //~ error: expected a pattern, found an expression + x.0 => (), //~ error: expected a pattern, found an expression + x._0 => (), //~ error: expected a pattern, found an expression + x.0.1 => (), //~ error: expected a pattern, found an expression + x.4.y.17.__z => (), //~ error: expected a pattern, found an expression + x.0e0 => (), //~ error: expected one of `=>`, `@`, `if`, or `|`, found `.` + } +} + +// MethodCallExpression, CallExpression, ErrorPropagationExpression +fn method_call() { + match 0 { + x.f() => (), //~ error: expected a pattern, found an expression + x._f() => (), //~ error: expected a pattern, found an expression + x? => (), //~ error: expected a pattern, found an expression + ().f() => (), //~ error: expected a pattern, found an expression + (0, x)?.f() => (), //~ error: expected a pattern, found an expression + x.f().g() => (), //~ error: expected a pattern, found an expression + 0.f()?.g()?? => (), //~ error: expected a pattern, found an expression + } +} + +// TypeCastExpression +fn type_cast() { + match 0 { + x as usize => (), //~ error: expected a pattern, found an expression + 0 as usize => (), //~ error: expected a pattern, found an expression + x.f().0.4 as f32 => (), //~ error: expected a pattern, found an expression + } +} + +// ArithmeticOrLogicalExpression +fn operator() { + match 0 { + 1 + 1 => (), //~ error: expected a pattern, found an expression + (1 + 2) * 3 => (), //~ error: expected a pattern, found an expression + } +} + +fn main() { + match u8::MAX { + u8::MAX.abs() => (), + //~^ error: expected a pattern, found an expression + x.sqrt() @ .. => (), + //~^ error: expected a pattern, found an expression + //~| error: left-hand side of `@` must be a binding + z @ w @ v.u() => (), + //~^ error: expected a pattern, found an expression + y.ilog(3) => (), + //~^ error: expected a pattern, found an expression + n + 1 => (), + //~^ error: expected a pattern, found an expression + ("".f() + 14 * 8) => (), + //~^ error: expected a pattern, found an expression + 0 | ((1) | 2) | 3 => (), + f?() => (), + //~^ error: expected a pattern, found an expression + (_ + 1) => (), + //~^ error: expected one of `)`, `,`, or `|`, found `+` + } + + let 1 + 1 = 2; + //~^ error: expected a pattern, found an expression + + let b = matches!(x, (x * x | x.f()) | x[0]); + //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*` +} diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr new file mode 100644 index 0000000000000..29905757bd851 --- /dev/null +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -0,0 +1,575 @@ +error: expected one of `=>`, `@`, `if`, or `|`, found `.` + --> $DIR/recover-pat-exprs.rs:10:10 + | +LL | x.0e0 => (), + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:5:9 + | +LL | x.y => (), + | ^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x.y => (), + | ~~~ +++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.y; +LL ~ match 0 { +LL | x => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | val if val == x.0 => (), + | ~~~ +++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.0; +LL ~ match 0 { +LL | x => (), +LL | x.y => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | val if val == x._0 => (), + | ~~~ ++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x._0; +LL ~ match 0 { +LL | x => (), +LL | x.y => (), +LL | x.0 => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | val if val == x.0.1 => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.0.1; +LL ~ match 0 { +LL | x => (), + ... +LL | x._0 => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | val if val == x.4.y.17.__z => (), + | ~~~ ++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.4.y.17.__z; +LL ~ match 0 { +LL | x => (), + ... +LL | x.0.1 => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x.4.y.17.__z } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:17:9 + | +LL | x.f() => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x.f() => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.f(); +LL ~ match 0 { +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x.f() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:18:9 + | +LL | x._f() => (), + | ^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x._f() => (), + | ~~~ ++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x._f(); +LL ~ match 0 { +LL | x.f() => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x._f() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:19:9 + | +LL | x? => (), + | ^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x? => (), + | ~~~ ++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x?; +LL ~ match 0 { +LL | x.f() => (), +LL | x._f() => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x? } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:20:9 + | +LL | ().f() => (), + | ^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == ().f() => (), + | ~~~ ++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = ().f(); +LL ~ match 0 { +LL | x.f() => (), +LL | x._f() => (), +LL | x? => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { ().f() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:21:9 + | +LL | (0, x)?.f() => (), + | ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == (0, x)?.f() => (), + | ~~~ +++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = (0, x)?.f(); +LL ~ match 0 { +LL | x.f() => (), + ... +LL | ().f() => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { (0, x)?.f() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:22:9 + | +LL | x.f().g() => (), + | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x.f().g() => (), + | ~~~ +++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.f().g(); +LL ~ match 0 { +LL | x.f() => (), + ... +LL | (0, x)?.f() => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x.f().g() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:23:9 + | +LL | 0.f()?.g()?? => (), + | ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == 0.f()?.g()?? => (), + | ~~~ ++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 0.f()?.g()??; +LL ~ match 0 { +LL | x.f() => (), + ... +LL | x.f().g() => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { 0.f()?.g()?? } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:30:9 + | +LL | x as usize => (), + | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x as usize => (), + | ~~~ ++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x as usize; +LL ~ match 0 { +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x as usize } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:31:9 + | +LL | 0 as usize => (), + | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == 0 as usize => (), + | ~~~ ++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 0 as usize; +LL ~ match 0 { +LL | x as usize => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { 0 as usize } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:32:9 + | +LL | x.f().0.4 as f32 => (), + | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == x.f().0.4 as f32 => (), + | ~~~ ++++++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = x.f().0.4 as f32; +LL ~ match 0 { +LL | x as usize => (), +LL | 0 as usize => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { x.f().0.4 as f32 } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:39:9 + | +LL | 1 + 1 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == 1 + 1 => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 1 + 1; +LL ~ match 0 { +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { 1 + 1 } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:40:9 + | +LL | (1 + 2) * 3 => (), + | ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == (1 + 2) * 3 => (), + | ~~~ +++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = (1 + 2) * 3; +LL ~ match 0 { +LL | 1 + 1 => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { (1 + 2) * 3 } => (), + | +++++++ + + +error: left-hand side of `@` must be a binding + --> $DIR/recover-pat-exprs.rs:48:9 + | +LL | x.sqrt() @ .. => (), + | --------^^^-- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: expected one of `)`, `,`, or `|`, found `+` + --> $DIR/recover-pat-exprs.rs:62:12 + | +LL | (_ + 1) => (), + | ^ expected one of `)`, `,`, or `|` + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:46:9 + | +LL | u8::MAX.abs() => (), + | ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == u8::MAX.abs() => (), + | ~~~ +++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = u8::MAX.abs(); +LL ~ match u8::MAX { +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { u8::MAX.abs() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:51:17 + | +LL | z @ w @ v.u() => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | z @ w @ val if val == v.u() => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = v.u(); +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), + ... +LL | +LL ~ z @ w @ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | z @ w @ const { v.u() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:53:9 + | +LL | y.ilog(3) => (), + | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == y.ilog(3) => (), + | ~~~ +++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = y.ilog(3); +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), + ... +LL | +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { y.ilog(3) } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:55:9 + | +LL | n + 1 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == n + 1 => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = n + 1; +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), + ... +LL | +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { n + 1 } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:57:10 + | +LL | ("".f() + 14 * 8) => (), + | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | (val) if val == "".f() + 14 * 8 => (), + | ~~~ +++++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = "".f() + 14 * 8; +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), + ... +LL | +LL ~ (VAL) => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | (const { "".f() + 14 * 8 }) => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:60:9 + | +LL | f?() => (), + | ^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | val if val == f?() => (), + | ~~~ ++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = f?(); +LL ~ match u8::MAX { +LL | u8::MAX.abs() => (), + ... +LL | 0 | ((1) | 2) | 3 => (), +LL ~ VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | const { f?() } => (), + | +++++++ + + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:66:9 + | +LL | let 1 + 1 = 2; + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: expected one of `)`, `,`, `@`, or `|`, found `*` + --> $DIR/recover-pat-exprs.rs:69:28 + | +LL | let b = matches!(x, (x * x | x.f()) | x[0]); + | ^ expected one of `)`, `,`, `@`, or `|` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: while parsing argument for this `pat` macro fragment + +error: expected a pattern, found an expression + --> $DIR/recover-pat-exprs.rs:48:9 + | +LL | x.sqrt() @ .. => (), + | ^^^^^^^^ arbitrary expressions are not allowed in patterns + +error: aborting due to 29 previous errors + diff --git a/tests/ui/parser/pat-recover-methodcalls.rs b/tests/ui/parser/recover/recover-pat-issues.rs similarity index 77% rename from tests/ui/parser/pat-recover-methodcalls.rs rename to tests/ui/parser/recover/recover-pat-issues.rs index 049a49fc98cee..5b900fe80e516 100644 --- a/tests/ui/parser/pat-recover-methodcalls.rs +++ b/tests/ui/parser/recover/recover-pat-issues.rs @@ -17,7 +17,8 @@ fn bar(bar: Bar) -> bool { } } -fn baz() { // issue #90121 +/// Issue #90121 +fn baz() { let foo = vec!["foo".to_string()]; match foo.as_slice() { @@ -27,6 +28,15 @@ fn baz() { // issue #90121 }; } +/// Issue #104996 +fn qux() { + struct Magic(pub u16); + const MAGIC: Magic = Magic(42); + + if let Some(MAGIC.0 as usize) = None:: {} + //~^ error: expected a pattern, found an expression +} + fn main() { if let (-1.some(4)) = (0, Some(4)) {} //~^ error: expected a pattern, found an expression diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr new file mode 100644 index 0000000000000..deea2730a269d --- /dev/null +++ b/tests/ui/parser/recover/recover-pat-issues.stderr @@ -0,0 +1,113 @@ +error: expected a pattern, found an expression + --> $DIR/recover-pat-issues.rs:6:13 + | +LL | Foo("hi".to_owned()) => true, + | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | +help: check the value in an arm guard + | +LL | Foo(val) if val == "hi".to_owned() => true, + | ~~~ +++++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = "hi".to_owned(); +LL ~ match foo { +LL ~ Foo(VAL) => true, + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | Bar { baz } if baz == "hi".to_owned() => true, + | ~~~ +++++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const BAZ: _ = "hi".to_owned(); +LL ~ match bar { +LL ~ Bar { baz: BAZ } => true, + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | &[val] if val == "foo".to_string() => {} + | ~~~ +++++++++++++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = "foo".to_string(); +LL ~ match foo.as_slice() { +LL ~ &[VAL] => {} + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = MAGIC.0 as usize; +LL ~ if let Some(VAL) = None:: {} + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = -1.some(4); +LL ~ if let (VAL) = (0, Some(4)) {} + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = -1.Some(4); +LL ~ if let (VAL) = (0, Some(4)) {} + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | if let (const { -1.Some(4) }) = (0, Some(4)) {} + | +++++++ + + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/pat-recover-ranges.rs b/tests/ui/parser/recover/recover-pat-ranges.rs similarity index 100% rename from tests/ui/parser/pat-recover-ranges.rs rename to tests/ui/parser/recover/recover-pat-ranges.rs diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr new file mode 100644 index 0000000000000..1ce4b5a837728 --- /dev/null +++ b/tests/ui/parser/recover/recover-pat-ranges.stderr @@ -0,0 +1,240 @@ +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:4:13 + | +LL | 0..=(1) => (), + | ^ ^ + | +help: remove these parentheses + | +LL - 0..=(1) => (), +LL + 0..=1 => (), + | + +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:6:9 + | +LL | (-12)..=4 => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (-12)..=4 => (), +LL + -12..=4 => (), + | + +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:8:9 + | +LL | (0)..=(-4) => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (0)..=(-4) => (), +LL + 0..=(-4) => (), + | + +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:8:15 + | +LL | (0)..=(-4) => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (0)..=(-4) => (), +LL + (0)..=-4 => (), + | + +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:13:9 + | +LL | (4).. => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (4).. => (), +LL + 4.. => (), + | + +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:15:9 + | +LL | (-4 + 0).. => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (-4 + 0).. => (), +LL + -4 + 0.. => (), + | + +error: range pattern bounds cannot have parentheses + --> $DIR/recover-pat-ranges.rs:18:9 + | +LL | (1 + 4)...1 * 2 => (), + | ^ ^ + | +help: remove these parentheses + | +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: check the value in an arm guard + | +LL | ..=val if val == 1 + 2 => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 1 + 2; +LL ~ match -1 { +LL | 0..=1 => (), + ... +LL | +LL ~ ..=VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | (val).. if val == -4 + 0 => (), + | ~~~ ++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = -4 + 0; +LL ~ match -1 { +LL | 0..=1 => (), + ... +LL | +LL ~ (VAL).. => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | (val)...1 * 2 if val == 1 + 4 => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 1 + 4; +LL ~ match -1 { +LL | 0..=1 => (), + ... +LL | +LL ~ (VAL)...1 * 2 => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | (1 + 4)...val if val == 1 * 2 => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 1 * 2; +LL ~ match -1 { +LL | 0..=1 => (), + ... +LL | +LL ~ (1 + 4)...VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | val..="y".z() if val == 0.x() => (), + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 0.x(); +LL ~ match -1 { +LL | 0..=1 => (), + ... +LL | +LL ~ VAL..="y".z() => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +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: check the value in an arm guard + | +LL | 0.x()..=val if val == "y".z() => (), + | ~~~ +++++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = "y".z(); +LL ~ match -1 { +LL | 0..=1 => (), + ... +LL | +LL ~ 0.x()..=VAL => (), + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | 0.x()..=const { "y".z() } => (), + | +++++++ + + +warning: `...` range patterns are deprecated + --> $DIR/recover-pat-ranges.rs:18:16 + | +LL | (1 + 4)...1 * 2 => (), + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default + +error: aborting due to 13 previous errors; 1 warning emitted + diff --git a/tests/ui/parser/pat-recover-wildcards.rs b/tests/ui/parser/recover/recover-pat-wildcards.rs similarity index 100% rename from tests/ui/parser/pat-recover-wildcards.rs rename to tests/ui/parser/recover/recover-pat-wildcards.rs diff --git a/tests/ui/parser/pat-recover-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr similarity index 66% rename from tests/ui/parser/pat-recover-wildcards.stderr rename to tests/ui/parser/recover/recover-pat-wildcards.stderr index 2b0c9bbc5be86..77364d569554d 100644 --- a/tests/ui/parser/pat-recover-wildcards.stderr +++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr @@ -1,35 +1,35 @@ error: expected one of `=>`, `if`, or `|`, found `+` - --> $DIR/pat-recover-wildcards.rs:5:11 + --> $DIR/recover-pat-wildcards.rs:5:11 | LL | _ + 1 => () | ^ expected one of `=>`, `if`, or `|` error: expected one of `)`, `,`, or `|`, found `%` - --> $DIR/pat-recover-wildcards.rs:11:12 + --> $DIR/recover-pat-wildcards.rs:11:12 | LL | (_ % 4) => () | ^ expected one of `)`, `,`, or `|` error: expected one of `=>`, `if`, or `|`, found `.` - --> $DIR/pat-recover-wildcards.rs:17:10 + --> $DIR/recover-pat-wildcards.rs:17:10 | LL | _.x() => () | ^ expected one of `=>`, `if`, or `|` error: expected one of `=>`, `if`, or `|`, found `..=` - --> $DIR/pat-recover-wildcards.rs:23:10 + --> $DIR/recover-pat-wildcards.rs:23:10 | LL | _..=4 => () | ^^^ expected one of `=>`, `if`, or `|` error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` - --> $DIR/pat-recover-wildcards.rs:29:11 + --> $DIR/recover-pat-wildcards.rs:29:11 | LL | .._ => () | ^ expected one of `=>`, `if`, or `|` error[E0586]: inclusive range with no end - --> $DIR/pat-recover-wildcards.rs:35:10 + --> $DIR/recover-pat-wildcards.rs:35:10 | LL | 0..._ => () | ^^^ help: use `..` instead @@ -37,31 +37,25 @@ LL | 0..._ => () = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` - --> $DIR/pat-recover-wildcards.rs:35:13 + --> $DIR/recover-pat-wildcards.rs:35:13 | LL | 0..._ => () | ^ expected one of `=>`, `if`, or `|` error: expected one of `)`, `,`, or `|`, found `*` - --> $DIR/pat-recover-wildcards.rs:43:12 + --> $DIR/recover-pat-wildcards.rs:43:12 | LL | (_ * 0)..5 => () | ^ expected one of `)`, `,`, or `|` error: expected one of `=>`, `if`, or `|`, found `(` - --> $DIR/pat-recover-wildcards.rs:49:11 + --> $DIR/recover-pat-wildcards.rs:49:11 | LL | ..(_) => () | ^ expected one of `=>`, `if`, or `|` -error: expected a pattern range bound, found an expression - --> $DIR/pat-recover-wildcards.rs:55:14 - | -LL | 4..=(2 + _) => () - | ^^^^^ arbitrary expressions are not allowed in patterns - error: range pattern bounds cannot have parentheses - --> $DIR/pat-recover-wildcards.rs:55:13 + --> $DIR/recover-pat-wildcards.rs:55:13 | LL | 4..=(2 + _) => () | ^ ^ @@ -72,6 +66,27 @@ 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: check the value in an arm guard + | +LL | 4..=(val) if val == 2 + _ => () + | ~~~ +++++++++++++++ +help: extract the expression into a `const` and refer to it + | +LL + const VAL: _ = 2 + _; +LL ~ match 9 { +LL ~ 4..=(VAL) => () + | +help: wrap the expression in a inline const (requires `#![feature(inline_const)]`) + | +LL | 4..=(const { 2 + _ }) => () + | +++++++ + + error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0586`.