I don’t know if it’s that obviously missing. After all, what can you do with negated patterns? Not bind any variables, can you? So it is basically just a boolean test, something that can be expressed with negated matches
in a guard. Of course, currently you cannot easily add guards to an if let
. However something like
if let Err(err @ not Fatal) = fn_returning_result() {
...
}
first rewritten as
match fn_returning_result() {
Err(err @ not Fatal) => {
...
}
_ => (),
}
can then be translated into current Rust syntax by means of
match fn_returning_result() {
Err(err) if !(matches!(err, Fatal)) => {
...
}
_ => (),
}
And in the future, something like
if let Err(err) = fn_returning_result() && !(matches!(err, Fatal)) {
...
}
will probably become possible.
Even something like Foo(not Some(not Fatal))
can already be written like this (admitted not very neat)
Foo(inner) if !(matches!(inner, Some(error) if !(matches!(error, Fatal))))
(in this case Foo(None) | Foo(Some(Fatal))
would way less confusing though)
Of yourse we could thing about introducing a general way to turn guards into patterns (which would then automatically give rise to macro-definable negative patterns if you really want them. I think currently more obvious shortcomings of Rust’s pattern matching are for example that it’s impossible to write patterns that look into Rc
or Box
.