If you're trying to optimize an enum's size it can be nice to use different variants instead of booleans. But it comes with a tradeoff: code reuse.
So you have this large enum with things like StringKey and NonValidatingStringKey and you have to copy-paste the code for StringKey into the NonValidatingStringKey match case because they do slightly different things, e.g.
match foo {
StringKey(x) => {
//code here
return option.map(Some).ok_or_else(|| ValidationError(etc, etc))
},
NonValidatingStringKey(x) => {
//pretty much exact same code here
return Ok(option)
}
}
It'd be nice if you could do something like this:
match foo {
StringKey(x) as let skip=false | NonValidatingStringKey(x) as let skip=true => {
//code here
if skip {
return Ok(option)
} else {
return option.map(Some).ok_or_else(|| ValidationError(etc, etc))
}
}
}
So you get all of the benefits of fallthrough (aka code reuse) with none of the drawbacks (because it's not fallthrough).
I believe that if let guards are planned, but they always apply to the entire match arm. This restriction could be removed by requiring parentheses in some cases:
match foo {
A | B if bar => {}
// is equivalent to
(A | B) if bar => {}
// This could be allowed too:
(A if bar) | (B if !bar) => {}
(A if let x = true) | (B if let x = false) => {}
}
Yeah, that's what we're currently using. We believe it has some issues that need to be acknowledged tho, like accidentally using different pattern_elements in the match and in the matches!.
This one is particular is basically @CAD97's suggestion, factored out into a translation method (From impl maybe) so that there's only one place to make those mistakes.
A key important thing to note here is that this doesn't have to be the version of the enum that you store and pass around. It can be a transient form that you just create temporarily to make it easier to work with.
We still gain the memory usage savings when doing that?
Also: What do we lose from not having a replacement for fall-through? Rust has enums, as a replacement for tagged unions. Rust uh wait did we ever merge/stabilize label-break-value? as an alternative to goto. Having something that's more restrictive than fall-through, but still enables some common fall-through-related ergonomics, would be nice.
You could solve that by creating an fn is_skip(&self) -> bool method and just calling it before (or after) you match. You can always mis-write code. The normal solution to that kind of thing is to separate concerns behind different abstractions.