Auto merge of #123877 - ShE3py:expr-in-pats-2, r=fmease

Further improve diagnostics for expressions in pattern position

Follow-up of #118625, see #121697.

```rs
fn main() {
    match 'b' {
        y.0.0.1.z().f()? as u32 => {},
    }
}
```
Before:
```
error: expected one of `=>`, ``@`,` `if`, or `|`, found `.`
 --> src/main.rs:3:10
  |
3 |         y.0.0.1.z().f()? as u32 => {},
  |          ^ expected one of `=>`, ``@`,` `if`, or `|`
```
After:
```
error: expected a pattern, found an expression
 --> src/main.rs:3:9
  |
3 |         y.0.0.1.z().f()? as u32 => {},
  |         ^^^^^^^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
  |
help: consider moving the expression to a match arm guard
  |
3 |         val if val == y.0.0.1.z().f()? as u32 => {},
  |         ~~~ +++++++++++++++++++++++++++++++++
help: consider extracting the expression into a `const`
  |
2 +     const VAL: /* Type */ = y.0.0.1.z().f()? as u32;
3 ~     match 'b' {
4 ~         VAL => {},
  |
help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
  |
3 |         const { y.0.0.1.z().f()? as u32 } => {},
  |         +++++++                         +
```

---

r? fmease
`@rustbot` label +A-diagnostics +A-parser +A-patterns +C-enhancement
This commit is contained in:
bors 2024-09-19 00:36:33 +00:00
commit df7f77811c
27 changed files with 1813 additions and 412 deletions

View File

@ -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<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {

View File

@ -803,15 +803,17 @@ parse_unexpected_expr_in_pat =
expected {$is_bound ->
[true] a pattern range bound
*[false] a pattern
}, found {$is_method_call ->
[true] a method call
*[false] an expression
}
}, found an expression
.label = {$is_method_call ->
[true] method calls
*[false] arbitrary expressions
} are not allowed in patterns
.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`

View File

@ -1,3 +1,5 @@
// ignore-tidy-filelength
use std::borrow::Cow;
use rustc_ast::token::Token;
@ -2592,13 +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,
/// Was the unexpected expression a `MethodCallExpression`?
pub is_method_call: 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<Span>,
/// 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)]

View File

@ -41,7 +41,7 @@ use super::{
use crate::{errors, maybe_recover_from_interpolated_ty_qpath};
#[derive(Debug)]
enum DestructuredFloat {
pub(super) enum DestructuredFloat {
/// 1e2
Single(Symbol, Span),
/// 1.
@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> {
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
// we should break everything including floats into more basic proc-macro style
// tokens in the lexer (probably preferable).
fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
#[derive(Debug)]
enum FloatComponent {
IdentLike(String),

View File

@ -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,11 +23,11 @@ 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;
use crate::parser::expr::{could_be_unclosed_char_literal, DestructuredFloat};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
#[derive(PartialEq, Copy, Clone)]
@ -342,7 +344,7 @@ impl<'a> Parser<'a> {
}
}
/// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator.
/// Ensures that the last parsed pattern (or pattern range bound) is not followed by an expression.
///
/// `is_end_bound` indicates whether the last parsed thing was the end bound of a range pattern (see [`parse_pat_range_end`](Self::parse_pat_range_end))
/// in order to say "expected a pattern range bound" instead of "expected a pattern";
@ -350,38 +352,64 @@ impl<'a> Parser<'a> {
/// 0..=1 + 2
/// ^^^^^
/// ```
/// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter.
/// Only the end bound is spanned in this case, and this function has no idea if there was a `..=` before `pat_span`, hence the parameter.
///
/// This function returns `Some` if a trailing expression was recovered, and said expression's span.
#[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"]
fn maybe_recover_trailing_expr(
&mut self,
pat_span: Span,
is_end_bound: bool,
) -> Option<ErrorGuaranteed> {
) -> Option<(ErrorGuaranteed, Span)> {
if self.prev_token.is_keyword(kw::Underscore) || !self.may_recover() {
// Don't recover anything after an `_` or if recovery is disabled.
return None;
}
// Check for `.hello()`, but allow `.Hello()` to be recovered as `, Hello()` in `parse_seq_to_before_tokens()`.
let has_trailing_method = self.check_noexpect(&token::Dot)
// Returns `true` iff `token` is an unsuffixed integer.
let is_one_tuple_index = |_: &Self, token: &Token| -> bool {
use token::{Lit, LitKind};
matches!(
token.kind,
token::Literal(Lit { kind: LitKind::Integer, symbol: _, suffix: None })
)
};
// Returns `true` iff `token` is an unsuffixed `x.y` float.
let is_two_tuple_indexes = |this: &Self, token: &Token| -> bool {
use token::{Lit, LitKind};
if let token::Literal(Lit { kind: LitKind::Float, symbol, suffix: None }) = token.kind
&& let DestructuredFloat::MiddleDot(..) = this.break_up_float(symbol, token.span)
{
true
} else {
false
}
};
// Check for `.hello` or `.0`.
let has_dot_expr = self.check_noexpect(&token::Dot) // `.`
&& self.look_ahead(1, |tok| {
tok.ident()
.and_then(|(ident, _)| ident.name.as_str().chars().next())
.is_some_and(char::is_lowercase)
})
&& self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Parenthesis));
tok.is_ident() // `hello`
|| is_one_tuple_index(&self, &tok) // `0`
|| is_two_tuple_indexes(&self, &tok) // `0.0`
});
// Check for operators.
// `|` is excluded as it is used in pattern alternatives and lambdas,
// `?` is included for error propagation,
// `[` is included for indexing operations,
// `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`)
// `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`),
// `as` is included for type casts
let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or)
|| self.token == token::Question
|| (self.token == token::OpenDelim(Delimiter::Bracket)
&& self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket)));
&& self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket))) // excludes `[]`
|| self.token.is_keyword(kw::As);
if !has_trailing_method && !has_trailing_operator {
if !has_dot_expr && !has_trailing_operator {
// Nothing to recover here.
return None;
}
@ -391,44 +419,248 @@ impl<'a> Parser<'a> {
snapshot.restrictions.insert(Restrictions::IS_PAT);
// Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
if let Ok(expr) = snapshot
let Ok(expr) = snapshot
.parse_expr_dot_or_call_with(
AttrVec::new(),
self.mk_expr(pat_span, ExprKind::Dummy), // equivalent to transforming the parsed pattern into an `Expr`
pat_span,
)
.map_err(|err| err.cancel())
{
let non_assoc_span = expr.span;
else {
// We got a trailing method/operator, but that wasn't an expression.
return None;
};
// Parse an associative expression such as `+ expr`, `% expr`, ...
// Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
if let Ok((expr, _)) =
snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
{
// We got a valid expression.
self.restore_snapshot(snapshot);
self.restrictions.remove(Restrictions::IS_PAT);
// Parse an associative expression such as `+ expr`, `% expr`, ...
// Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
let Ok((expr, _)) =
snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
else {
// We got a trailing method/operator, but that wasn't an expression.
return None;
};
let is_bound = is_end_bound
// is_start_bound: either `..` or `)..`
|| self.token.is_range_separator()
|| self.token == token::CloseDelim(Delimiter::Parenthesis)
&& self.look_ahead(1, Token::is_range_separator);
// We got a valid expression.
self.restore_snapshot(snapshot);
self.restrictions.remove(Restrictions::IS_PAT);
// Check that `parse_expr_assoc_with` didn't eat a rhs.
let is_method_call = has_trailing_method && non_assoc_span == expr.span;
let is_bound = is_end_bound
// is_start_bound: either `..` or `)..`
|| self.token.is_range_separator()
|| self.token == token::CloseDelim(Delimiter::Parenthesis)
&& self.look_ahead(1, Token::is_range_separator);
return Some(self.dcx().emit_err(UnexpectedExpressionInPattern {
span: expr.span,
let span = expr.span;
Some((
self.dcx()
.create_err(UnexpectedExpressionInPattern {
span,
is_bound,
is_method_call,
}));
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 <err>`) 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(),
});
}
},
);
}
}
// We got a trailing method/operator, but we couldn't parse an expression.
None
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 <err>`)
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
@ -544,7 +776,7 @@ impl<'a> Parser<'a> {
self.parse_pat_tuple_struct(qself, path)?
} else {
match self.maybe_recover_trailing_expr(span, false) {
Some(guar) => PatKind::Err(guar),
Some((guar, _)) => PatKind::Err(guar),
None => PatKind::Path(qself, path),
}
}
@ -577,10 +809,10 @@ impl<'a> Parser<'a> {
// Try to parse everything else as literal with optional minus
match self.parse_literal_maybe_minus() {
Ok(begin) => {
let begin = match self.maybe_recover_trailing_expr(begin.span, false) {
Some(guar) => self.mk_expr_err(begin.span, guar),
None => begin,
};
let begin = self
.maybe_recover_trailing_expr(begin.span, false)
.map(|(guar, sp)| self.mk_expr_err(sp, guar))
.unwrap_or(begin);
match self.parse_range_end() {
Some(form) => self.parse_pat_range_begin_with(begin, form)?,
@ -721,7 +953,8 @@ impl<'a> Parser<'a> {
// For backward compatibility, `(..)` is a tuple pattern as well.
let paren_pattern =
fields.len() == 1 && !(matches!(trailing_comma, Trailing::Yes) || fields[0].is_rest());
if paren_pattern {
let pat = if paren_pattern {
let pat = fields.into_iter().next().unwrap();
let close_paren = self.prev_token.span;
@ -739,7 +972,7 @@ impl<'a> Parser<'a> {
},
});
self.parse_pat_range_begin_with(begin.clone(), form)
self.parse_pat_range_begin_with(begin.clone(), form)?
}
// recover ranges with parentheses around the `(start)..`
PatKind::Err(guar)
@ -754,15 +987,20 @@ impl<'a> Parser<'a> {
},
});
self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)
self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)?
}
// (pat) with optional parentheses
_ => Ok(PatKind::Paren(pat)),
_ => PatKind::Paren(pat),
}
} else {
Ok(PatKind::Tuple(fields))
}
PatKind::Tuple(fields)
};
Ok(match self.maybe_recover_trailing_expr(open_paren.to(self.prev_token.span), false) {
None => pat,
Some((guar, _)) => PatKind::Err(guar),
})
}
/// Parse a mutable binding with the `mut` token already eaten.
@ -816,7 +1054,7 @@ impl<'a> Parser<'a> {
self.0 = true;
*m = Mutability::Mut;
}
walk_pat(self, pat);
mut_visit::walk_pat(self, pat);
}
}
@ -1015,7 +1253,7 @@ impl<'a> Parser<'a> {
}
Ok(match recovered {
Some(guar) => self.mk_expr_err(bound.span, guar),
Some((guar, sp)) => self.mk_expr_err(sp, guar),
None => bound,
})
}
@ -1084,7 +1322,7 @@ impl<'a> Parser<'a> {
// but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`.
let pat = if sub.is_none()
&& let Some(guar) = self.maybe_recover_trailing_expr(ident.span, false)
&& let Some((guar, _)) = self.maybe_recover_trailing_expr(ident.span, false)
{
PatKind::Err(guar)
} else {

View File

@ -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<Stmt>> {
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> {

View File

@ -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

View File

@ -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
|

View File

@ -1,5 +1,6 @@
//@ error-pattern: expected
fn main() {
let x.y::<isize>.z foo;
//~^ error: field expressions cannot have generic arguments
//~| error: expected a pattern, found an expression
//~| error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
}

View File

@ -1,8 +1,20 @@
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
--> $DIR/bad-name.rs:4:8
error: field expressions cannot have generic arguments
--> $DIR/bad-name.rs:2:12
|
LL | let x.y::<isize>.z foo;
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
| ^^^^^^^
error: aborting due to 1 previous error
error: expected a pattern, found an expression
--> $DIR/bad-name.rs:2:7
|
LL | let x.y::<isize>.z foo;
| ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
--> $DIR/bad-name.rs:2:22
|
LL | let x.y::<isize>.z foo;
| ^^^ expected one of 9 possible tokens
error: aborting due to 3 previous errors

View File

@ -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

View File

@ -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

View File

@ -1,28 +0,0 @@
fn main() {
match u8::MAX {
u8::MAX.abs() => (),
//~^ error: expected a pattern, found a method call
x.sqrt() @ .. => (),
//~^ error: expected a pattern, found a method call
//~| error: left-hand side of `@` must be a binding
z @ w @ v.u() => (),
//~^ error: expected a pattern, found a method call
y.ilog(3) => (),
//~^ error: expected a pattern, found a method call
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 `*`
}

View File

@ -1,76 +0,0 @@
error: expected a pattern, found a method call
--> $DIR/pat-recover-exprs.rs:3:9
|
LL | u8::MAX.abs() => (),
| ^^^^^^^^^^^^^ method calls are not allowed in patterns
error: expected a pattern, found a method call
--> $DIR/pat-recover-exprs.rs:5:9
|
LL | x.sqrt() @ .. => (),
| ^^^^^^^^ method calls 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 a method call
--> $DIR/pat-recover-exprs.rs:8:17
|
LL | z @ w @ v.u() => (),
| ^^^^^ method calls are not allowed in patterns
error: expected a pattern, found a method call
--> $DIR/pat-recover-exprs.rs:10:9
|
LL | y.ilog(3) => (),
| ^^^^^^^^^ method calls 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

View File

@ -1,37 +0,0 @@
struct Foo(String);
struct Bar { baz: String }
fn foo(foo: Foo) -> bool {
match foo {
Foo("hi".to_owned()) => true,
//~^ error: expected a pattern, found a method call
_ => false
}
}
fn bar(bar: Bar) -> bool {
match bar {
Bar { baz: "hi".to_owned() } => true,
//~^ error: expected a pattern, found a method call
_ => false
}
}
fn baz() { // issue #90121
let foo = vec!["foo".to_string()];
match foo.as_slice() {
&["foo".to_string()] => {}
//~^ error: expected a pattern, found a method call
_ => {}
};
}
fn main() {
if let (-1.some(4)) = (0, Some(4)) {}
//~^ error: expected a pattern, found a method call
if let (-1.Some(4)) = (0, Some(4)) {}
//~^ error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
//~| help: missing `,`
}

View File

@ -1,35 +0,0 @@
error: expected a pattern, found a method call
--> $DIR/pat-recover-methodcalls.rs:6:13
|
LL | Foo("hi".to_owned()) => true,
| ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
error: expected a pattern, found a method call
--> $DIR/pat-recover-methodcalls.rs:14:20
|
LL | Bar { baz: "hi".to_owned() } => true,
| ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
error: expected a pattern, found a method call
--> $DIR/pat-recover-methodcalls.rs:24:11
|
LL | &["foo".to_string()] => {}
| ^^^^^^^^^^^^^^^^^ method calls are not allowed in patterns
error: expected a pattern, found a method call
--> $DIR/pat-recover-methodcalls.rs:31:13
|
LL | if let (-1.some(4)) = (0, Some(4)) {}
| ^^^^^^^^^^ method calls are not allowed in patterns
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
--> $DIR/pat-recover-methodcalls.rs:34:15
|
LL | if let (-1.Some(4)) = (0, Some(4)) {}
| ^
| |
| expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
| help: missing `,`
error: aborting due to 5 previous errors

View File

@ -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 a method call
--> $DIR/pat-recover-ranges.rs:24:9
|
LL | 0.x()..="y".z() => (),
| ^^^^^ method calls are not allowed in patterns
error: expected a pattern range bound, found a method call
--> $DIR/pat-recover-ranges.rs:24:17
|
LL | 0.x()..="y".z() => (),
| ^^^^^^^ method calls 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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default
error: aborting due to 13 previous errors; 1 warning emitted

View File

@ -0,0 +1,106 @@
// 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
}
{ let x.0e0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
{ let x.-0.0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
{ let x.-0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
{ let x.0u32; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
{ let x.0.0_f64; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
}
// IndexExpression, ArrayExpression
fn array_indexing() {
match 0 {
x[0] => (), //~ error: expected a pattern, found an expression
x[..] => (), //~ error: expected a pattern, found an expression
}
{ let x[0, 1, 2]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
{ let x[0; 20]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
{ let x[]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
{ let (x[]); } //~ error: expected one of `)`, `,`, `@`, or `|`, found `[`
//~^ missing `,`
}
// 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, 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
}
}
const _: u32 = match 12 {
1 + 2 * PI.cos() => 2, //~ error: expected a pattern, found an expression
_ => 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 `*`
}

View File

@ -0,0 +1,772 @@
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: 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
|
LL | { let x.0e0; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
--> $DIR/recover-pat-exprs.rs:13:12
|
LL | { let x.-0.0; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
--> $DIR/recover-pat-exprs.rs:14:12
|
LL | { let x.-0; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
--> $DIR/recover-pat-exprs.rs:16:12
|
LL | { let x.0u32; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
--> $DIR/recover-pat-exprs.rs:17:12
|
LL | { let x.0.0_f64; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:23: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 ~ 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
|
LL | { let x[0, 1, 2]; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
--> $DIR/recover-pat-exprs.rs:28:12
|
LL | { let x[0; 20]; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
--> $DIR/recover-pat-exprs.rs:29:12
|
LL | { let x[]; }
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
error: expected one of `)`, `,`, `@`, or `|`, found `[`
--> $DIR/recover-pat-exprs.rs:30:13
|
LL | { let (x[]); }
| ^
| |
| expected one of `)`, `,`, `@`, or `|`
| help: missing `,`
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:37: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 ~ 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
|
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:63:9
|
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:64:9
|
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:83: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:97:12
|
LL | (_ + 1) => (),
| ^ expected one of `)`, `,`, or `|`
error: expected a pattern, found an expression
--> $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:104: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: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

View File

@ -0,0 +1,46 @@
struct Foo(String);
struct Bar { baz: String }
fn foo(foo: Foo) -> bool {
match foo {
Foo("hi".to_owned()) => true,
//~^ error: expected a pattern, found an expression
_ => false
}
}
fn bar(bar: Bar) -> bool {
match bar {
Bar { baz: "hi".to_owned() } => true,
//~^ error: expected a pattern, found an expression
_ => false
}
}
/// Issue #90121
fn baz() {
let foo = vec!["foo".to_string()];
match foo.as_slice() {
&["foo".to_string()] => {}
//~^ error: expected a pattern, found an expression
_ => {}
};
}
/// Issue #104996
fn qux() {
struct Magic(pub u16);
const MAGIC: Magic = Magic(42);
if let Some(MAGIC.0 as usize) = None::<usize> {}
//~^ error: expected a pattern, found an expression
}
fn main() {
if let (-1.some(4)) = (0, Some(4)) {}
//~^ error: expected a pattern, found an expression
if let (-1.Some(4)) = (0, Some(4)) {}
//~^ error: expected a pattern, found an expression
}

View File

@ -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: 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::<usize> {}
| ^^^^^^^^^^^^^^^^ 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::<usize> {}
|
help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
|
LL | if let Some(const { MAGIC.0 as usize }) = None::<usize> {}
| +++++++ +
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

View File

@ -0,0 +1,20 @@
fn main() {
let x = Some(2);
let x.expect("foo");
//~^ error: expected a pattern, found an expression
let x.unwrap(): u32;
//~^ error: expected a pattern, found an expression
let x[0] = 1;
//~^ error: expected a pattern, found an expression
let Some(1 + 1) = x else { //~ error: expected a pattern, found an expression
return;
};
if let Some(1 + 1) = x { //~ error: expected a pattern, found an expression
return;
}
}

View File

@ -0,0 +1,52 @@
error: expected a pattern, found an expression
--> $DIR/recover-pat-lets.rs:4:9
|
LL | let x.expect("foo");
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
error: expected a pattern, found an expression
--> $DIR/recover-pat-lets.rs:7:9
|
LL | let x.unwrap(): u32;
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
error: expected a pattern, found an expression
--> $DIR/recover-pat-lets.rs:10:9
|
LL | let x[0] = 1;
| ^^^^ arbitrary expressions are not allowed in patterns
error: expected a pattern, found an expression
--> $DIR/recover-pat-lets.rs:13:14
|
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

View File

@ -22,8 +22,8 @@ fn main() {
//~| warning: `...` range patterns are deprecated
//~| warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
0.x()..="y".z() => (),
//~^ error: expected a pattern range bound, found a method call
//~| error: expected a pattern range bound, found a method call
//~^ error: expected a pattern range bound, found an expression
//~| error: expected a pattern range bound, found an expression
};
}

View File

@ -0,0 +1,216 @@
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: 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
|
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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default
error: aborting due to 13 previous errors; 1 warning emitted

View File

@ -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..._ => ()
| ^^^
@ -42,31 +42,25 @@ LL + 0.._ => ()
|
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 + _) => ()
| ^ ^
@ -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`.