Skip to content

Further improve diagnostics for expressions in pattern position #123877

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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 {
18 changes: 10 additions & 8 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
@@ -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 = 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)]`)
.label = {$is_method_call ->
[true] method calls
*[false] arbitrary expressions
} are not allowed in patterns
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`
79 changes: 77 additions & 2 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
@@ -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)]
4 changes: 2 additions & 2 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
@@ -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),
354 changes: 296 additions & 58 deletions compiler/rustc_parse/src/parser/pat.rs

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
@@ -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> {
11 changes: 11 additions & 0 deletions tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
Original file line number Diff line number Diff line change
@@ -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
23 changes: 17 additions & 6 deletions tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
Original file line number Diff line number Diff line change
@@ -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
|
5 changes: 3 additions & 2 deletions tests/ui/parser/bad-name.rs
Original file line number Diff line number Diff line change
@@ -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`
}
20 changes: 16 additions & 4 deletions tests/ui/parser/bad-name.stderr
Original file line number Diff line number Diff line change
@@ -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

15 changes: 15 additions & 0 deletions tests/ui/parser/issues/issue-24375.stderr
Original file line number Diff line number Diff line change
@@ -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

4 changes: 2 additions & 2 deletions tests/ui/parser/pat-lt-bracket-6.stderr
Original file line number Diff line number Diff line change
@@ -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
28 changes: 0 additions & 28 deletions tests/ui/parser/pat-recover-exprs.rs

This file was deleted.

76 changes: 0 additions & 76 deletions tests/ui/parser/pat-recover-exprs.stderr

This file was deleted.

37 changes: 0 additions & 37 deletions tests/ui/parser/pat-recover-methodcalls.rs

This file was deleted.

35 changes: 0 additions & 35 deletions tests/ui/parser/pat-recover-methodcalls.stderr

This file was deleted.

132 changes: 0 additions & 132 deletions tests/ui/parser/pat-recover-ranges.stderr

This file was deleted.

106 changes: 106 additions & 0 deletions tests/ui/parser/recover/recover-pat-exprs.rs
Original file line number Diff line number Diff line change
@@ -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 `*`
}
772 changes: 772 additions & 0 deletions tests/ui/parser/recover/recover-pat-exprs.stderr

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions tests/ui/parser/recover/recover-pat-issues.rs
Original file line number Diff line number Diff line change
@@ -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
}
113 changes: 113 additions & 0 deletions tests/ui/parser/recover/recover-pat-issues.stderr
Original file line number Diff line number Diff line change
@@ -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

20 changes: 20 additions & 0 deletions tests/ui/parser/recover/recover-pat-lets.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}
52 changes: 52 additions & 0 deletions tests/ui/parser/recover/recover-pat-lets.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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
};
}

216 changes: 216 additions & 0 deletions tests/ui/parser/recover/recover-pat-ranges.stderr
Original file line number Diff line number Diff line change
@@ -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

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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`.