Description
Given the following code: [playground]
pub fn test(val: i32) {
match val {
(0 if true) => {}
_ => {}
}
}
The current output is:
error: expected identifier, found keyword `if`
--> src/lib.rs:3:12
|
3 | (0 if true) => {}
| ^^ expected identifier, found keyword
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found keyword `if`
--> src/lib.rs:3:12
|
3 | (0 if true) => {}
| -^^ expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
| |
| help: missing `,`
error: expected one of `)`, `,`, `@`, or `|`, found keyword `true`
--> src/lib.rs:3:15
|
3 | (0 if true) => {}
| -^^^^ expected one of `)`, `,`, `@`, or `|`
| |
| help: missing `,`
error[E0308]: mismatched types
--> src/lib.rs:3:9
|
2 | match val {
| --- this expression has type `i32`
3 | (0 if true) => {}
| ^^^^^^^^^^^ expected `i32`, found tuple
|
= note: expected type `i32`
found tuple `(_, _, _)`
Ideally the output should look like:
error: match pattern guard not allowed here
--> src/lib.rs:3:9
|
3 | (0 if true) => {}
| ^^^^^^^ not supported
|
= note: match pattern guards must appear at the top level
help: move the guard to the top level
|
3 - (_ if true) => {}
3 + (_) if true => {}
|
As-is, results in unused_parens
warning. Alternative help that doesn't:
help: remove these parentheses
|
3 - (0 if true) => {}
3 + 0 if true => {}
|
Bonus points:
-
Stash this error while parsing and tweak it later when types are available; e.g. if the scrutinee actually is
(_, _, _)
, perhaps(_, r#if, true)
(what this currently seemingly error-recovers as) actually was meant. With a non-tuple scrutinee, though, clearly the parenthesization was meant. -
Support parsing parenthesized guards in nested patterns and give the nice parser error there. Note that for the guard lifting to be semantics preserving, it must not exit any alt (
|
) pattern combinations.examples
Some(0 if true) => Some(_) if true; (0, 0 if true) => (0, 0) if true; (_ if true) | 0 => {} // cannot be written as a single pattern 0 | _ if true => 0 | _ if true; // is a valid pattern: (0 | _) if true Struct { field: 0 if true } => Struct { field: 0 } if true;
@rustbot label +D-confusing +D-verbose
(Is this
D-invalid-suggestion
help
is not moving towards correct code.)