Skip to content

Commit c204721

Browse files
committedSep 18, 2024
Recover more expressions in patterns
1 parent 7fc70f8 commit c204721

20 files changed

+633
-282
lines changed
 

‎compiler/rustc_parse/messages.ftl

+2-8
Original file line numberDiff line numberDiff line change
@@ -803,15 +803,9 @@ parse_unexpected_expr_in_pat =
803803
expected {$is_bound ->
804804
[true] a pattern range bound
805805
*[false] a pattern
806-
}, found {$is_method_call ->
807-
[true] a method call
808-
*[false] an expression
809-
}
806+
}, found an expression
810807
811-
.label = {$is_method_call ->
812-
[true] method calls
813-
*[false] arbitrary expressions
814-
} are not allowed in patterns
808+
.label = arbitrary expressions are not allowed in patterns
815809
816810
parse_unexpected_if_with_if = unexpected `if` in the condition expression
817811
.suggestion = remove the `if`

‎compiler/rustc_parse/src/errors.rs

-2
Original file line numberDiff line numberDiff line change
@@ -2597,8 +2597,6 @@ pub(crate) struct UnexpectedExpressionInPattern {
25972597
pub span: Span,
25982598
/// Was a `RangePatternBound` expected?
25992599
pub is_bound: bool,
2600-
/// Was the unexpected expression a `MethodCallExpression`?
2601-
pub is_method_call: bool,
26022600
}
26032601

26042602
#[derive(Diagnostic)]

‎compiler/rustc_parse/src/parser/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use super::{
4141
use crate::{errors, maybe_recover_from_interpolated_ty_qpath};
4242

4343
#[derive(Debug)]
44-
enum DestructuredFloat {
44+
pub(super) enum DestructuredFloat {
4545
/// 1e2
4646
Single(Symbol, Span),
4747
/// 1.
@@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> {
10411041
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
10421042
// we should break everything including floats into more basic proc-macro style
10431043
// tokens in the lexer (probably preferable).
1044-
fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
1044+
pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
10451045
#[derive(Debug)]
10461046
enum FloatComponent {
10471047
IdentLike(String),

‎compiler/rustc_parse/src/parser/pat.rs

+86-57
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::errors::{
2525
UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
2626
UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
2727
};
28-
use crate::parser::expr::could_be_unclosed_char_literal;
28+
use crate::parser::expr::{could_be_unclosed_char_literal, DestructuredFloat};
2929
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
3030

3131
#[derive(PartialEq, Copy, Clone)]
@@ -342,46 +342,72 @@ impl<'a> Parser<'a> {
342342
}
343343
}
344344

345-
/// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator.
345+
/// Ensures that the last parsed pattern (or pattern range bound) is not followed by an expression.
346346
///
347347
/// `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))
348348
/// in order to say "expected a pattern range bound" instead of "expected a pattern";
349349
/// ```text
350350
/// 0..=1 + 2
351351
/// ^^^^^
352352
/// ```
353-
/// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter.
353+
/// 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.
354+
///
355+
/// This function returns `Some` if a trailing expression was recovered, and said expression's span.
354356
#[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"]
355357
fn maybe_recover_trailing_expr(
356358
&mut self,
357359
pat_span: Span,
358360
is_end_bound: bool,
359-
) -> Option<ErrorGuaranteed> {
361+
) -> Option<(ErrorGuaranteed, Span)> {
360362
if self.prev_token.is_keyword(kw::Underscore) || !self.may_recover() {
361363
// Don't recover anything after an `_` or if recovery is disabled.
362364
return None;
363365
}
364366

365-
// Check for `.hello()`, but allow `.Hello()` to be recovered as `, Hello()` in `parse_seq_to_before_tokens()`.
366-
let has_trailing_method = self.check_noexpect(&token::Dot)
367+
// Returns `true` iff `token` is an unsuffixed integer.
368+
let is_one_tuple_index = |_: &Self, token: &Token| -> bool {
369+
use token::{Lit, LitKind};
370+
371+
matches!(
372+
token.kind,
373+
token::Literal(Lit { kind: LitKind::Integer, symbol: _, suffix: None })
374+
)
375+
};
376+
377+
// Returns `true` iff `token` is an unsuffixed `x.y` float.
378+
let is_two_tuple_indexes = |this: &Self, token: &Token| -> bool {
379+
use token::{Lit, LitKind};
380+
381+
if let token::Literal(Lit { kind: LitKind::Float, symbol, suffix: None }) = token.kind
382+
&& let DestructuredFloat::MiddleDot(..) = this.break_up_float(symbol, token.span)
383+
{
384+
true
385+
} else {
386+
false
387+
}
388+
};
389+
390+
// Check for `.hello` or `.0`.
391+
let has_dot_expr = self.check_noexpect(&token::Dot) // `.`
367392
&& self.look_ahead(1, |tok| {
368-
tok.ident()
369-
.and_then(|(ident, _)| ident.name.as_str().chars().next())
370-
.is_some_and(char::is_lowercase)
371-
})
372-
&& self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Parenthesis));
393+
tok.is_ident() // `hello`
394+
|| is_one_tuple_index(&self, &tok) // `0`
395+
|| is_two_tuple_indexes(&self, &tok) // `0.0`
396+
});
373397

374398
// Check for operators.
375399
// `|` is excluded as it is used in pattern alternatives and lambdas,
376400
// `?` is included for error propagation,
377401
// `[` is included for indexing operations,
378-
// `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`)
402+
// `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`),
403+
// `as` is included for type casts
379404
let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or)
380405
|| self.token == token::Question
381406
|| (self.token == token::OpenDelim(Delimiter::Bracket)
382-
&& self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket)));
407+
&& self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket))) // excludes `[]`
408+
|| self.token.is_keyword(kw::As);
383409

384-
if !has_trailing_method && !has_trailing_operator {
410+
if !has_dot_expr && !has_trailing_operator {
385411
// Nothing to recover here.
386412
return None;
387413
}
@@ -391,44 +417,41 @@ impl<'a> Parser<'a> {
391417
snapshot.restrictions.insert(Restrictions::IS_PAT);
392418

393419
// Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
394-
if let Ok(expr) = snapshot
420+
let Ok(expr) = snapshot
395421
.parse_expr_dot_or_call_with(
396422
AttrVec::new(),
397423
self.mk_expr(pat_span, ExprKind::Dummy), // equivalent to transforming the parsed pattern into an `Expr`
398424
pat_span,
399425
)
400426
.map_err(|err| err.cancel())
401-
{
402-
let non_assoc_span = expr.span;
427+
else {
428+
// We got a trailing method/operator, but that wasn't an expression.
429+
return None;
430+
};
403431

404-
// Parse an associative expression such as `+ expr`, `% expr`, ...
405-
// Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
406-
if let Ok((expr, _)) =
407-
snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
408-
{
409-
// We got a valid expression.
410-
self.restore_snapshot(snapshot);
411-
self.restrictions.remove(Restrictions::IS_PAT);
412-
413-
let is_bound = is_end_bound
414-
// is_start_bound: either `..` or `)..`
415-
|| self.token.is_range_separator()
416-
|| self.token == token::CloseDelim(Delimiter::Parenthesis)
417-
&& self.look_ahead(1, Token::is_range_separator);
418-
419-
// Check that `parse_expr_assoc_with` didn't eat a rhs.
420-
let is_method_call = has_trailing_method && non_assoc_span == expr.span;
421-
422-
return Some(self.dcx().emit_err(UnexpectedExpressionInPattern {
423-
span: expr.span,
424-
is_bound,
425-
is_method_call,
426-
}));
427-
}
428-
}
432+
// Parse an associative expression such as `+ expr`, `% expr`, ...
433+
// Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
434+
let Ok((expr, _)) =
435+
snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
436+
else {
437+
// We got a trailing method/operator, but that wasn't an expression.
438+
return None;
439+
};
429440

430-
// We got a trailing method/operator, but we couldn't parse an expression.
431-
None
441+
// We got a valid expression.
442+
self.restore_snapshot(snapshot);
443+
self.restrictions.remove(Restrictions::IS_PAT);
444+
445+
let is_bound = is_end_bound
446+
// is_start_bound: either `..` or `)..`
447+
|| self.token.is_range_separator()
448+
|| self.token == token::CloseDelim(Delimiter::Parenthesis)
449+
&& self.look_ahead(1, Token::is_range_separator);
450+
451+
Some((
452+
self.dcx().emit_err(UnexpectedExpressionInPattern { span: expr.span, is_bound }),
453+
expr.span,
454+
))
432455
}
433456

434457
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
@@ -544,7 +567,7 @@ impl<'a> Parser<'a> {
544567
self.parse_pat_tuple_struct(qself, path)?
545568
} else {
546569
match self.maybe_recover_trailing_expr(span, false) {
547-
Some(guar) => PatKind::Err(guar),
570+
Some((guar, _)) => PatKind::Err(guar),
548571
None => PatKind::Path(qself, path),
549572
}
550573
}
@@ -577,10 +600,10 @@ impl<'a> Parser<'a> {
577600
// Try to parse everything else as literal with optional minus
578601
match self.parse_literal_maybe_minus() {
579602
Ok(begin) => {
580-
let begin = match self.maybe_recover_trailing_expr(begin.span, false) {
581-
Some(guar) => self.mk_expr_err(begin.span, guar),
582-
None => begin,
583-
};
603+
let begin = self
604+
.maybe_recover_trailing_expr(begin.span, false)
605+
.map(|(guar, sp)| self.mk_expr_err(sp, guar))
606+
.unwrap_or(begin);
584607

585608
match self.parse_range_end() {
586609
Some(form) => self.parse_pat_range_begin_with(begin, form)?,
@@ -721,7 +744,8 @@ impl<'a> Parser<'a> {
721744
// For backward compatibility, `(..)` is a tuple pattern as well.
722745
let paren_pattern =
723746
fields.len() == 1 && !(matches!(trailing_comma, Trailing::Yes) || fields[0].is_rest());
724-
if paren_pattern {
747+
748+
let pat = if paren_pattern {
725749
let pat = fields.into_iter().next().unwrap();
726750
let close_paren = self.prev_token.span;
727751

@@ -739,7 +763,7 @@ impl<'a> Parser<'a> {
739763
},
740764
});
741765

742-
self.parse_pat_range_begin_with(begin.clone(), form)
766+
self.parse_pat_range_begin_with(begin.clone(), form)?
743767
}
744768
// recover ranges with parentheses around the `(start)..`
745769
PatKind::Err(guar)
@@ -754,15 +778,20 @@ impl<'a> Parser<'a> {
754778
},
755779
});
756780

757-
self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)
781+
self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)?
758782
}
759783

760784
// (pat) with optional parentheses
761-
_ => Ok(PatKind::Paren(pat)),
785+
_ => PatKind::Paren(pat),
762786
}
763787
} else {
764-
Ok(PatKind::Tuple(fields))
765-
}
788+
PatKind::Tuple(fields)
789+
};
790+
791+
Ok(match self.maybe_recover_trailing_expr(open_paren.to(self.prev_token.span), false) {
792+
None => pat,
793+
Some((guar, _)) => PatKind::Err(guar),
794+
})
766795
}
767796

768797
/// Parse a mutable binding with the `mut` token already eaten.
@@ -1015,7 +1044,7 @@ impl<'a> Parser<'a> {
10151044
}
10161045

10171046
Ok(match recovered {
1018-
Some(guar) => self.mk_expr_err(bound.span, guar),
1047+
Some((guar, sp)) => self.mk_expr_err(sp, guar),
10191048
None => bound,
10201049
})
10211050
}
@@ -1084,7 +1113,7 @@ impl<'a> Parser<'a> {
10841113
// but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`.
10851114

10861115
let pat = if sub.is_none()
1087-
&& let Some(guar) = self.maybe_recover_trailing_expr(ident.span, false)
1116+
&& let Some((guar, _)) = self.maybe_recover_trailing_expr(ident.span, false)
10881117
{
10891118
PatKind::Err(guar)
10901119
} else {

‎tests/ui/parser/bad-name.rs

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

‎tests/ui/parser/bad-name.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1-
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
2-
--> $DIR/bad-name.rs:4:8
1+
error: field expressions cannot have generic arguments
2+
--> $DIR/bad-name.rs:2:12
33
|
44
LL | let x.y::<isize>.z foo;
5-
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
5+
| ^^^^^^^
66

7-
error: aborting due to 1 previous error
7+
error: expected a pattern, found an expression
8+
--> $DIR/bad-name.rs:2:7
9+
|
10+
LL | let x.y::<isize>.z foo;
11+
| ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
12+
13+
error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
14+
--> $DIR/bad-name.rs:2:22
15+
|
16+
LL | let x.y::<isize>.z foo;
17+
| ^^^ expected one of 9 possible tokens
18+
19+
error: aborting due to 3 previous errors
820

‎tests/ui/parser/pat-recover-exprs.rs

-28
This file was deleted.

‎tests/ui/parser/pat-recover-exprs.stderr

-76
This file was deleted.

‎tests/ui/parser/pat-recover-methodcalls.rs

-37
This file was deleted.

‎tests/ui/parser/pat-recover-methodcalls.stderr

-35
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// FieldExpression, TupleIndexingExpression
2+
fn field_access() {
3+
match 0 {
4+
x => (),
5+
x.y => (), //~ error: expected a pattern, found an expression
6+
x.0 => (), //~ error: expected a pattern, found an expression
7+
x._0 => (), //~ error: expected a pattern, found an expression
8+
x.0.1 => (), //~ error: expected a pattern, found an expression
9+
x.4.y.17.__z => (), //~ error: expected a pattern, found an expression
10+
}
11+
12+
{ let x.0e0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
13+
{ let x.-0.0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
14+
{ let x.-0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
15+
16+
{ let x.0u32; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
17+
{ let x.0.0_f64; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
18+
}
19+
20+
// IndexExpression, ArrayExpression
21+
fn array_indexing() {
22+
match 0 {
23+
x[0] => (), //~ error: expected a pattern, found an expression
24+
x[..] => (), //~ error: expected a pattern, found an expression
25+
}
26+
27+
{ let x[0, 1, 2]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
28+
{ let x[0; 20]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
29+
{ let x[]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
30+
{ let (x[]); } //~ error: expected one of `)`, `,`, `@`, or `|`, found `[`
31+
//~^ missing `,`
32+
}
33+
34+
// MethodCallExpression, CallExpression, ErrorPropagationExpression
35+
fn method_call() {
36+
match 0 {
37+
x.f() => (), //~ error: expected a pattern, found an expression
38+
x._f() => (), //~ error: expected a pattern, found an expression
39+
x? => (), //~ error: expected a pattern, found an expression
40+
().f() => (), //~ error: expected a pattern, found an expression
41+
(0, x)?.f() => (), //~ error: expected a pattern, found an expression
42+
x.f().g() => (), //~ error: expected a pattern, found an expression
43+
0.f()?.g()?? => (), //~ error: expected a pattern, found an expression
44+
}
45+
}
46+
47+
// TypeCastExpression
48+
fn type_cast() {
49+
match 0 {
50+
x as usize => (), //~ error: expected a pattern, found an expression
51+
0 as usize => (), //~ error: expected a pattern, found an expression
52+
x.f().0.4 as f32 => (), //~ error: expected a pattern, found an expression
53+
}
54+
}
55+
56+
// ArithmeticOrLogicalExpression
57+
fn operator() {
58+
match 0 {
59+
1 + 1 => (), //~ error: expected a pattern, found an expression
60+
(1 + 2) * 3 => (),
61+
//~^ error: expected a pattern, found an expression
62+
//~| error: expected a pattern, found an expression
63+
}
64+
}
65+
66+
const _: u32 = match 12 {
67+
1 + 2 * PI.cos() => 2, //~ error: expected a pattern, found an expression
68+
_ => 0,
69+
};
70+
71+
fn main() {
72+
match u8::MAX {
73+
u8::MAX.abs() => (),
74+
//~^ error: expected a pattern, found an expression
75+
x.sqrt() @ .. => (),
76+
//~^ error: expected a pattern, found an expression
77+
//~| error: left-hand side of `@` must be a binding
78+
z @ w @ v.u() => (),
79+
//~^ error: expected a pattern, found an expression
80+
y.ilog(3) => (),
81+
//~^ error: expected a pattern, found an expression
82+
n + 1 => (),
83+
//~^ error: expected a pattern, found an expression
84+
("".f() + 14 * 8) => (),
85+
//~^ error: expected a pattern, found an expression
86+
0 | ((1) | 2) | 3 => (),
87+
f?() => (),
88+
//~^ error: expected a pattern, found an expression
89+
(_ + 1) => (),
90+
//~^ error: expected one of `)`, `,`, or `|`, found `+`
91+
}
92+
93+
let 1 + 1 = 2;
94+
//~^ error: expected a pattern, found an expression
95+
96+
let b = matches!(x, (x * x | x.f()) | x[0]);
97+
//~^ error: expected one of `)`, `,`, `@`, or `|`, found `*`
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
error: expected a pattern, found an expression
2+
--> $DIR/recover-pat-exprs.rs:5:9
3+
|
4+
LL | x.y => (),
5+
| ^^^ arbitrary expressions are not allowed in patterns
6+
7+
error: expected a pattern, found an expression
8+
--> $DIR/recover-pat-exprs.rs:6:9
9+
|
10+
LL | x.0 => (),
11+
| ^^^ arbitrary expressions are not allowed in patterns
12+
13+
error: expected a pattern, found an expression
14+
--> $DIR/recover-pat-exprs.rs:7:9
15+
|
16+
LL | x._0 => (),
17+
| ^^^^ arbitrary expressions are not allowed in patterns
18+
19+
error: expected a pattern, found an expression
20+
--> $DIR/recover-pat-exprs.rs:8:9
21+
|
22+
LL | x.0.1 => (),
23+
| ^^^^^ arbitrary expressions are not allowed in patterns
24+
25+
error: expected a pattern, found an expression
26+
--> $DIR/recover-pat-exprs.rs:9:9
27+
|
28+
LL | x.4.y.17.__z => (),
29+
| ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
30+
31+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
32+
--> $DIR/recover-pat-exprs.rs:12:12
33+
|
34+
LL | { let x.0e0; }
35+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
36+
37+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
38+
--> $DIR/recover-pat-exprs.rs:13:12
39+
|
40+
LL | { let x.-0.0; }
41+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
42+
43+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
44+
--> $DIR/recover-pat-exprs.rs:14:12
45+
|
46+
LL | { let x.-0; }
47+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
48+
49+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
50+
--> $DIR/recover-pat-exprs.rs:16:12
51+
|
52+
LL | { let x.0u32; }
53+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
54+
55+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
56+
--> $DIR/recover-pat-exprs.rs:17:12
57+
|
58+
LL | { let x.0.0_f64; }
59+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
60+
61+
error: expected a pattern, found an expression
62+
--> $DIR/recover-pat-exprs.rs:23:9
63+
|
64+
LL | x[0] => (),
65+
| ^^^^ arbitrary expressions are not allowed in patterns
66+
67+
error: expected a pattern, found an expression
68+
--> $DIR/recover-pat-exprs.rs:24:9
69+
|
70+
LL | x[..] => (),
71+
| ^^^^^ arbitrary expressions are not allowed in patterns
72+
73+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
74+
--> $DIR/recover-pat-exprs.rs:27:12
75+
|
76+
LL | { let x[0, 1, 2]; }
77+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
78+
79+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
80+
--> $DIR/recover-pat-exprs.rs:28:12
81+
|
82+
LL | { let x[0; 20]; }
83+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
84+
85+
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
86+
--> $DIR/recover-pat-exprs.rs:29:12
87+
|
88+
LL | { let x[]; }
89+
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
90+
91+
error: expected one of `)`, `,`, `@`, or `|`, found `[`
92+
--> $DIR/recover-pat-exprs.rs:30:13
93+
|
94+
LL | { let (x[]); }
95+
| ^
96+
| |
97+
| expected one of `)`, `,`, `@`, or `|`
98+
| help: missing `,`
99+
100+
error: expected a pattern, found an expression
101+
--> $DIR/recover-pat-exprs.rs:37:9
102+
|
103+
LL | x.f() => (),
104+
| ^^^^^ arbitrary expressions are not allowed in patterns
105+
106+
error: expected a pattern, found an expression
107+
--> $DIR/recover-pat-exprs.rs:38:9
108+
|
109+
LL | x._f() => (),
110+
| ^^^^^^ arbitrary expressions are not allowed in patterns
111+
112+
error: expected a pattern, found an expression
113+
--> $DIR/recover-pat-exprs.rs:39:9
114+
|
115+
LL | x? => (),
116+
| ^^ arbitrary expressions are not allowed in patterns
117+
118+
error: expected a pattern, found an expression
119+
--> $DIR/recover-pat-exprs.rs:40:9
120+
|
121+
LL | ().f() => (),
122+
| ^^^^^^ arbitrary expressions are not allowed in patterns
123+
124+
error: expected a pattern, found an expression
125+
--> $DIR/recover-pat-exprs.rs:41:9
126+
|
127+
LL | (0, x)?.f() => (),
128+
| ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
129+
130+
error: expected a pattern, found an expression
131+
--> $DIR/recover-pat-exprs.rs:42:9
132+
|
133+
LL | x.f().g() => (),
134+
| ^^^^^^^^^ arbitrary expressions are not allowed in patterns
135+
136+
error: expected a pattern, found an expression
137+
--> $DIR/recover-pat-exprs.rs:43:9
138+
|
139+
LL | 0.f()?.g()?? => (),
140+
| ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
141+
142+
error: expected a pattern, found an expression
143+
--> $DIR/recover-pat-exprs.rs:50:9
144+
|
145+
LL | x as usize => (),
146+
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
147+
148+
error: expected a pattern, found an expression
149+
--> $DIR/recover-pat-exprs.rs:51:9
150+
|
151+
LL | 0 as usize => (),
152+
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
153+
154+
error: expected a pattern, found an expression
155+
--> $DIR/recover-pat-exprs.rs:52:9
156+
|
157+
LL | x.f().0.4 as f32 => (),
158+
| ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
159+
160+
error: expected a pattern, found an expression
161+
--> $DIR/recover-pat-exprs.rs:59:9
162+
|
163+
LL | 1 + 1 => (),
164+
| ^^^^^ arbitrary expressions are not allowed in patterns
165+
166+
error: expected a pattern, found an expression
167+
--> $DIR/recover-pat-exprs.rs:60:10
168+
|
169+
LL | (1 + 2) * 3 => (),
170+
| ^^^^^ arbitrary expressions are not allowed in patterns
171+
172+
error: expected a pattern, found an expression
173+
--> $DIR/recover-pat-exprs.rs:60:9
174+
|
175+
LL | (1 + 2) * 3 => (),
176+
| ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
177+
178+
error: expected a pattern, found an expression
179+
--> $DIR/recover-pat-exprs.rs:67:5
180+
|
181+
LL | 1 + 2 * PI.cos() => 2,
182+
| ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
183+
184+
error: expected a pattern, found an expression
185+
--> $DIR/recover-pat-exprs.rs:73:9
186+
|
187+
LL | u8::MAX.abs() => (),
188+
| ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
189+
190+
error: expected a pattern, found an expression
191+
--> $DIR/recover-pat-exprs.rs:75:9
192+
|
193+
LL | x.sqrt() @ .. => (),
194+
| ^^^^^^^^ arbitrary expressions are not allowed in patterns
195+
196+
error: left-hand side of `@` must be a binding
197+
--> $DIR/recover-pat-exprs.rs:75:9
198+
|
199+
LL | x.sqrt() @ .. => (),
200+
| --------^^^--
201+
| | |
202+
| | also a pattern
203+
| interpreted as a pattern, not a binding
204+
|
205+
= note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
206+
207+
error: expected a pattern, found an expression
208+
--> $DIR/recover-pat-exprs.rs:78:17
209+
|
210+
LL | z @ w @ v.u() => (),
211+
| ^^^^^ arbitrary expressions are not allowed in patterns
212+
213+
error: expected a pattern, found an expression
214+
--> $DIR/recover-pat-exprs.rs:80:9
215+
|
216+
LL | y.ilog(3) => (),
217+
| ^^^^^^^^^ arbitrary expressions are not allowed in patterns
218+
219+
error: expected a pattern, found an expression
220+
--> $DIR/recover-pat-exprs.rs:82:9
221+
|
222+
LL | n + 1 => (),
223+
| ^^^^^ arbitrary expressions are not allowed in patterns
224+
225+
error: expected a pattern, found an expression
226+
--> $DIR/recover-pat-exprs.rs:84:10
227+
|
228+
LL | ("".f() + 14 * 8) => (),
229+
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
230+
231+
error: expected a pattern, found an expression
232+
--> $DIR/recover-pat-exprs.rs:87:9
233+
|
234+
LL | f?() => (),
235+
| ^^^^ arbitrary expressions are not allowed in patterns
236+
237+
error: expected one of `)`, `,`, or `|`, found `+`
238+
--> $DIR/recover-pat-exprs.rs:89:12
239+
|
240+
LL | (_ + 1) => (),
241+
| ^ expected one of `)`, `,`, or `|`
242+
243+
error: expected a pattern, found an expression
244+
--> $DIR/recover-pat-exprs.rs:93:9
245+
|
246+
LL | let 1 + 1 = 2;
247+
| ^^^^^ arbitrary expressions are not allowed in patterns
248+
249+
error: expected one of `)`, `,`, `@`, or `|`, found `*`
250+
--> $DIR/recover-pat-exprs.rs:96:28
251+
|
252+
LL | let b = matches!(x, (x * x | x.f()) | x[0]);
253+
| ^ expected one of `)`, `,`, `@`, or `|`
254+
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
255+
|
256+
= note: while parsing argument for this `pat` macro fragment
257+
258+
error: aborting due to 41 previous errors
259+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
struct Foo(String);
2+
struct Bar { baz: String }
3+
4+
fn foo(foo: Foo) -> bool {
5+
match foo {
6+
Foo("hi".to_owned()) => true,
7+
//~^ error: expected a pattern, found an expression
8+
_ => false
9+
}
10+
}
11+
12+
fn bar(bar: Bar) -> bool {
13+
match bar {
14+
Bar { baz: "hi".to_owned() } => true,
15+
//~^ error: expected a pattern, found an expression
16+
_ => false
17+
}
18+
}
19+
20+
/// Issue #90121
21+
fn baz() {
22+
let foo = vec!["foo".to_string()];
23+
24+
match foo.as_slice() {
25+
&["foo".to_string()] => {}
26+
//~^ error: expected a pattern, found an expression
27+
_ => {}
28+
};
29+
}
30+
31+
/// Issue #104996
32+
fn qux() {
33+
struct Magic(pub u16);
34+
const MAGIC: Magic = Magic(42);
35+
36+
if let Some(MAGIC.0 as usize) = None::<usize> {}
37+
//~^ error: expected a pattern, found an expression
38+
}
39+
40+
fn main() {
41+
if let (-1.some(4)) = (0, Some(4)) {}
42+
//~^ error: expected a pattern, found an expression
43+
44+
if let (-1.Some(4)) = (0, Some(4)) {}
45+
//~^ error: expected a pattern, found an expression
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: expected a pattern, found an expression
2+
--> $DIR/recover-pat-issues.rs:6:13
3+
|
4+
LL | Foo("hi".to_owned()) => true,
5+
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
6+
7+
error: expected a pattern, found an expression
8+
--> $DIR/recover-pat-issues.rs:14:20
9+
|
10+
LL | Bar { baz: "hi".to_owned() } => true,
11+
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
12+
13+
error: expected a pattern, found an expression
14+
--> $DIR/recover-pat-issues.rs:25:11
15+
|
16+
LL | &["foo".to_string()] => {}
17+
| ^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
18+
19+
error: expected a pattern, found an expression
20+
--> $DIR/recover-pat-issues.rs:36:17
21+
|
22+
LL | if let Some(MAGIC.0 as usize) = None::<usize> {}
23+
| ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
24+
25+
error: expected a pattern, found an expression
26+
--> $DIR/recover-pat-issues.rs:41:13
27+
|
28+
LL | if let (-1.some(4)) = (0, Some(4)) {}
29+
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
30+
31+
error: expected a pattern, found an expression
32+
--> $DIR/recover-pat-issues.rs:44:13
33+
|
34+
LL | if let (-1.Some(4)) = (0, Some(4)) {}
35+
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
36+
37+
error: aborting due to 6 previous errors
38+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fn main() {
2+
let x = Some(2);
3+
4+
let x.expect("foo");
5+
//~^ error: expected a pattern, found an expression
6+
7+
let x.unwrap(): u32;
8+
//~^ error: expected a pattern, found an expression
9+
10+
let x[0] = 1;
11+
//~^ error: expected a pattern, found an expression
12+
13+
let Some(1 + 1) = x else { //~ error: expected a pattern, found an expression
14+
return;
15+
};
16+
17+
if let Some(1 + 1) = x { //~ error: expected a pattern, found an expression
18+
return;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: expected a pattern, found an expression
2+
--> $DIR/recover-pat-lets.rs:4:9
3+
|
4+
LL | let x.expect("foo");
5+
| ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
6+
7+
error: expected a pattern, found an expression
8+
--> $DIR/recover-pat-lets.rs:7:9
9+
|
10+
LL | let x.unwrap(): u32;
11+
| ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
12+
13+
error: expected a pattern, found an expression
14+
--> $DIR/recover-pat-lets.rs:10:9
15+
|
16+
LL | let x[0] = 1;
17+
| ^^^^ arbitrary expressions are not allowed in patterns
18+
19+
error: expected a pattern, found an expression
20+
--> $DIR/recover-pat-lets.rs:13:14
21+
|
22+
LL | let Some(1 + 1) = x else {
23+
| ^^^^^ arbitrary expressions are not allowed in patterns
24+
25+
error: expected a pattern, found an expression
26+
--> $DIR/recover-pat-lets.rs:17:17
27+
|
28+
LL | if let Some(1 + 1) = x {
29+
| ^^^^^ arbitrary expressions are not allowed in patterns
30+
31+
error: aborting due to 5 previous errors
32+

‎tests/ui/parser/pat-recover-ranges.rs renamed to ‎tests/ui/parser/recover/recover-pat-ranges.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ fn main() {
2222
//~| warning: `...` range patterns are deprecated
2323
//~| warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
2424
0.x()..="y".z() => (),
25-
//~^ error: expected a pattern range bound, found a method call
26-
//~| error: expected a pattern range bound, found a method call
25+
//~^ error: expected a pattern range bound, found an expression
26+
//~| error: expected a pattern range bound, found an expression
2727
};
2828
}
2929

‎tests/ui/parser/pat-recover-ranges.stderr renamed to ‎tests/ui/parser/recover/recover-pat-ranges.stderr

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: range pattern bounds cannot have parentheses
2-
--> $DIR/pat-recover-ranges.rs:4:13
2+
--> $DIR/recover-pat-ranges.rs:4:13
33
|
44
LL | 0..=(1) => (),
55
| ^ ^
@@ -11,7 +11,7 @@ LL + 0..=1 => (),
1111
|
1212

1313
error: range pattern bounds cannot have parentheses
14-
--> $DIR/pat-recover-ranges.rs:6:9
14+
--> $DIR/recover-pat-ranges.rs:6:9
1515
|
1616
LL | (-12)..=4 => (),
1717
| ^ ^
@@ -23,7 +23,7 @@ LL + -12..=4 => (),
2323
|
2424

2525
error: range pattern bounds cannot have parentheses
26-
--> $DIR/pat-recover-ranges.rs:8:9
26+
--> $DIR/recover-pat-ranges.rs:8:9
2727
|
2828
LL | (0)..=(-4) => (),
2929
| ^ ^
@@ -35,7 +35,7 @@ LL + 0..=(-4) => (),
3535
|
3636

3737
error: range pattern bounds cannot have parentheses
38-
--> $DIR/pat-recover-ranges.rs:8:15
38+
--> $DIR/recover-pat-ranges.rs:8:15
3939
|
4040
LL | (0)..=(-4) => (),
4141
| ^ ^
@@ -47,13 +47,13 @@ LL + (0)..=-4 => (),
4747
|
4848

4949
error: expected a pattern range bound, found an expression
50-
--> $DIR/pat-recover-ranges.rs:11:12
50+
--> $DIR/recover-pat-ranges.rs:11:12
5151
|
5252
LL | ..=1 + 2 => (),
5353
| ^^^^^ arbitrary expressions are not allowed in patterns
5454

5555
error: range pattern bounds cannot have parentheses
56-
--> $DIR/pat-recover-ranges.rs:13:9
56+
--> $DIR/recover-pat-ranges.rs:13:9
5757
|
5858
LL | (4).. => (),
5959
| ^ ^
@@ -65,13 +65,13 @@ LL + 4.. => (),
6565
|
6666

6767
error: expected a pattern range bound, found an expression
68-
--> $DIR/pat-recover-ranges.rs:15:10
68+
--> $DIR/recover-pat-ranges.rs:15:10
6969
|
7070
LL | (-4 + 0).. => (),
7171
| ^^^^^^ arbitrary expressions are not allowed in patterns
7272

7373
error: range pattern bounds cannot have parentheses
74-
--> $DIR/pat-recover-ranges.rs:15:9
74+
--> $DIR/recover-pat-ranges.rs:15:9
7575
|
7676
LL | (-4 + 0).. => (),
7777
| ^ ^
@@ -83,13 +83,13 @@ LL + -4 + 0.. => (),
8383
|
8484

8585
error: expected a pattern range bound, found an expression
86-
--> $DIR/pat-recover-ranges.rs:18:10
86+
--> $DIR/recover-pat-ranges.rs:18:10
8787
|
8888
LL | (1 + 4)...1 * 2 => (),
8989
| ^^^^^ arbitrary expressions are not allowed in patterns
9090

9191
error: range pattern bounds cannot have parentheses
92-
--> $DIR/pat-recover-ranges.rs:18:9
92+
--> $DIR/recover-pat-ranges.rs:18:9
9393
|
9494
LL | (1 + 4)...1 * 2 => (),
9595
| ^ ^
@@ -101,25 +101,25 @@ LL + 1 + 4...1 * 2 => (),
101101
|
102102

103103
error: expected a pattern range bound, found an expression
104-
--> $DIR/pat-recover-ranges.rs:18:19
104+
--> $DIR/recover-pat-ranges.rs:18:19
105105
|
106106
LL | (1 + 4)...1 * 2 => (),
107107
| ^^^^^ arbitrary expressions are not allowed in patterns
108108

109-
error: expected a pattern range bound, found a method call
110-
--> $DIR/pat-recover-ranges.rs:24:9
109+
error: expected a pattern range bound, found an expression
110+
--> $DIR/recover-pat-ranges.rs:24:9
111111
|
112112
LL | 0.x()..="y".z() => (),
113-
| ^^^^^ method calls are not allowed in patterns
113+
| ^^^^^ arbitrary expressions are not allowed in patterns
114114

115-
error: expected a pattern range bound, found a method call
116-
--> $DIR/pat-recover-ranges.rs:24:17
115+
error: expected a pattern range bound, found an expression
116+
--> $DIR/recover-pat-ranges.rs:24:17
117117
|
118118
LL | 0.x()..="y".z() => (),
119-
| ^^^^^^^ method calls are not allowed in patterns
119+
| ^^^^^^^ arbitrary expressions are not allowed in patterns
120120

121121
warning: `...` range patterns are deprecated
122-
--> $DIR/pat-recover-ranges.rs:18:16
122+
--> $DIR/recover-pat-ranges.rs:18:16
123123
|
124124
LL | (1 + 4)...1 * 2 => (),
125125
| ^^^ help: use `..=` for an inclusive range

‎tests/ui/parser/pat-recover-wildcards.stderr renamed to ‎tests/ui/parser/recover/recover-pat-wildcards.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
error: expected one of `=>`, `if`, or `|`, found `+`
2-
--> $DIR/pat-recover-wildcards.rs:5:11
2+
--> $DIR/recover-pat-wildcards.rs:5:11
33
|
44
LL | _ + 1 => ()
55
| ^ expected one of `=>`, `if`, or `|`
66

77
error: expected one of `)`, `,`, or `|`, found `%`
8-
--> $DIR/pat-recover-wildcards.rs:11:12
8+
--> $DIR/recover-pat-wildcards.rs:11:12
99
|
1010
LL | (_ % 4) => ()
1111
| ^ expected one of `)`, `,`, or `|`
1212

1313
error: expected one of `=>`, `if`, or `|`, found `.`
14-
--> $DIR/pat-recover-wildcards.rs:17:10
14+
--> $DIR/recover-pat-wildcards.rs:17:10
1515
|
1616
LL | _.x() => ()
1717
| ^ expected one of `=>`, `if`, or `|`
1818

1919
error: expected one of `=>`, `if`, or `|`, found `..=`
20-
--> $DIR/pat-recover-wildcards.rs:23:10
20+
--> $DIR/recover-pat-wildcards.rs:23:10
2121
|
2222
LL | _..=4 => ()
2323
| ^^^ expected one of `=>`, `if`, or `|`
2424

2525
error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
26-
--> $DIR/pat-recover-wildcards.rs:29:11
26+
--> $DIR/recover-pat-wildcards.rs:29:11
2727
|
2828
LL | .._ => ()
2929
| ^ expected one of `=>`, `if`, or `|`
3030

3131
error[E0586]: inclusive range with no end
32-
--> $DIR/pat-recover-wildcards.rs:35:10
32+
--> $DIR/recover-pat-wildcards.rs:35:10
3333
|
3434
LL | 0..._ => ()
3535
| ^^^
@@ -42,31 +42,31 @@ LL + 0.._ => ()
4242
|
4343

4444
error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
45-
--> $DIR/pat-recover-wildcards.rs:35:13
45+
--> $DIR/recover-pat-wildcards.rs:35:13
4646
|
4747
LL | 0..._ => ()
4848
| ^ expected one of `=>`, `if`, or `|`
4949

5050
error: expected one of `)`, `,`, or `|`, found `*`
51-
--> $DIR/pat-recover-wildcards.rs:43:12
51+
--> $DIR/recover-pat-wildcards.rs:43:12
5252
|
5353
LL | (_ * 0)..5 => ()
5454
| ^ expected one of `)`, `,`, or `|`
5555

5656
error: expected one of `=>`, `if`, or `|`, found `(`
57-
--> $DIR/pat-recover-wildcards.rs:49:11
57+
--> $DIR/recover-pat-wildcards.rs:49:11
5858
|
5959
LL | ..(_) => ()
6060
| ^ expected one of `=>`, `if`, or `|`
6161

6262
error: expected a pattern range bound, found an expression
63-
--> $DIR/pat-recover-wildcards.rs:55:14
63+
--> $DIR/recover-pat-wildcards.rs:55:14
6464
|
6565
LL | 4..=(2 + _) => ()
6666
| ^^^^^ arbitrary expressions are not allowed in patterns
6767

6868
error: range pattern bounds cannot have parentheses
69-
--> $DIR/pat-recover-wildcards.rs:55:13
69+
--> $DIR/recover-pat-wildcards.rs:55:13
7070
|
7171
LL | 4..=(2 + _) => ()
7272
| ^ ^

0 commit comments

Comments
 (0)
Please sign in to comment.