You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rollup merge of rust-lang#118625 - ShE3py:expr-in-pats, r=WaffleLapkin
Improve handling of expressions in patterns
Closesrust-lang#112593.
Methodcalls' dots in patterns are silently recovered as commas (e.g. `Foo("".len())` -> `Foo("", len())`) so extra diagnostics are emitted:
```rs
struct Foo(u8, String, u8);
fn bar(foo: Foo) -> bool {
match foo {
Foo(4, "yippee".yeet(), 7) => true,
_ => false
}
}
```
```
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
--> main.rs:5:24
|
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^
| |
| expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
| help: missing `,`
error[E0531]: cannot find tuple struct or tuple variant `yeet` in this scope
--> main.rs:5:25
|
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^^^^ not found in this scope
error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
--> main.rs:5:13
|
1 | struct Foo(u8, String, u8);
| -- ------ -- tuple struct has 3 fields
...
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^ ^^^^^^^^ ^^^^^^ ^ expected 3 fields, found 4
error: aborting due to 3 previous errors
```
This PR checks for patterns that ends with a dot and a lowercase ident (as structs/variants should be uppercase):
```
error: expected a pattern, found a method call
--> main.rs:5:16
|
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
error: aborting due to 1 previous error
```
Also check for expressions:
```rs
fn is_idempotent(x: f32) -> bool {
match x {
x * x => true,
_ => false,
}
}
fn main() {
let mut t: [i32; 5];
let t[0] = 1;
}
```
```
error: expected a pattern, found an expression
--> main.rs:3:9
|
3 | x * x => true,
| ^^^^^ arbitrary expressions are not allowed in patterns
error: expected a pattern, found an expression
--> main.rs:10:9
|
10 | let t[0] = 1;
| ^^^^ arbitrary expressions are not allowed in patterns
```
Would be cool if the compiler could suggest adding a guard for `match`es, but I've no idea how to do it.
---
`@rustbot` label +A-diagnostics +A-parser +A-patterns +C-enhancement
@@ -23,7 +23,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
23
23
use rustc_session::errors::ExprParenthesesNeeded;
24
24
use rustc_span::source_map::{respan,Spanned};
25
25
use rustc_span::symbol::{kw, sym,Ident};
26
-
use rustc_span::Span;
26
+
use rustc_span::{ErrorGuaranteed,Span};
27
27
use thin_vec::{thin_vec,ThinVec};
28
28
29
29
#[derive(PartialEq,Copy,Clone)]
@@ -336,6 +336,95 @@ impl<'a> Parser<'a> {
336
336
}
337
337
}
338
338
339
+
/// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator.
340
+
///
341
+
/// `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))
342
+
/// in order to say "expected a pattern range bound" instead of "expected a pattern";
343
+
/// ```text
344
+
/// 0..=1 + 2
345
+
/// ^^^^^
346
+
/// ```
347
+
/// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter.
348
+
#[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"]
0 commit comments