rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Allow `_ @ CONST` in match arms

Open mahkoh opened this issue 5 years ago • 5 comments

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.

mahkoh avatar Jun 04 '20 15:06 mahkoh

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.

kennytm avatar Jun 04 '20 15:06 kennytm

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.

mahkoh avatar Jun 04 '20 15:06 mahkoh

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).

kennytm avatar Jun 04 '20 15:06 kennytm

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?

scottmcm avatar Jun 09 '20 07:06 scottmcm

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

igotfr avatar Apr 30 '22 22:04 igotfr