rfcs
rfcs copied to clipboard
Allow `_ @ CONST` in match arms
The following is currently not valid:
const CONST: u32 = 1;
fn main() {
let x = 2;
match x {
_ @ CONST => { },
_ => { }
}
}
error: pattern on wrong side of `@`
--> src/main.rs:6:6
|
6 | _ @ CONST => { },
| -^^^-----
| | |
| | binding on the right, should be on the left
| pattern on the left, should be on the right
| help: switch the order: `CONST @ _`
Apparently because the grammar requires an identifier on the lhs of @. Replacing _ by _x makes the code compile.
Writing
match x {
CONST => { },
_ => { }
}
is ambiguous without a complete analysis of the surrounding module. CONST might be a variable name or a constant. The difference impacts which arm is taken.
On the other hand,
match x {
_x @ CONST => { },
_ => { }
}
is unambiguous but introduces the useless variable _x.
Therefore my proposal is as follows:
- Make
match x {
_ @ CONST => { },
_ => { }
}
valid syntax.
- Deprecate
match x {
CONST => { },
_ => { }
}
where CONST could either be a constant or a variable name in the next edition.
with #2920 you could also write
match x {
const { CONST } => { },
_ => { },
}
furthermore, because of rust-lang/rust#65490, it is not an error that the CONST in _x @ CONST being another variable.
The problem with _x @ CONST is that it adds useless noise. const { CONST } is unfortunately even noisier.
Using const { CONST } also does not fix the ambiguity (for the reader not the compiler) of code using plain CONST in a match pattern. Consider
match x {
CONST1 => { },
CONST2 => { },
}
The compiler will warn you if you forgot to import CONST2 but only because CONST2 is not snake case. This can easily slip through code review and if this particular warning was disabled or if there are many warnings anyway, it might not get caught at all.
if we follow the roadmap in https://github.com/rust-lang/rfcs/issues/263#issuecomment-427629005 treating @ as pattern intersection, _ @ CONST would naturally be supported but not having the effect OP desired (if you forget to import CONST there won't be error).
I raised the const { CONST } version on IRLO about two months back: https://internals.rust-lang.org/t/bring-enum-variants-in-scope-for-patterns/12104/51?u=scottmcm
There are two interesting replies that suggest the extra noise from requiring the keyword in the pattern would be too annoying for the value.
We're very good at emitting at least one warning in the mistaken cases here; is there maybe a subset that we could upgrade to be deny-by-default because it's so unlikely to be correct?
I would like this to be allowed:
let n = 4;
match n {
_ @ 2..=7 => println!("between 2 and 7"),
_ => println!("not between 2 and 7")
}
the match between 4 and 2..=7 doesn't make sense