- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Guarded Match Exhaustiveness Testing
Fri, 2012-01-06, 00:14
It seems that guarded match expressions are not tested for
completeness at compile time. For example, the following code will
compile without "warning: match is not exhaustive!", even though
calling it with a value of 1 will result in a MatchError.
def foo(x: Option[Int]): Int = x match {
case Some(n) if n % 2 == 0 => n
case None => 0
}
The equivalent code in Ocaml does print a non-exhaustive match warning
at compile time.
let foo(x) =
match x with
| Some n when n mod 2 = 0 -> n
| None -> 0;;
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
Some _
(However, some guarded clause may match this value.)
val foo : int option -> int =
Obviously the compiler can’t decide whether or not arbitrary
combinations of guards are complete, but I was surprised didn’t treat
guards pessimistically like Ocaml does. This actually bit us in
production code, when a method like this:
def foo(x: Option[Int]): Int = x match {
case Some(n) if n % 2 == 0 => n
case _ => 0
}
was refactored to look like this:
def foo(x: Option[Int]): Int = x match {
case Some(n) if n % 2 == 0 => n
case None => 0
}
which resulted in runtime MatchErrors.
I understand that adding a warning that treats guarded match
statements pessimistically could be annoying in cases when the
combined guards actually are safe, but in these instances the warning
could easily be dismissed with an annotation or a no-op unguarded
match. Why don’t we give Scala users the option for added safety?
-Jon
Fri, 2012-01-13, 05:11
#2
Re: Re: Guarded Match Exhaustiveness Testing
On Mon, Jan 9, 2012 at 6:13 AM, Adriaan Moors <adriaan.moors@gmail.com> wrote:
It doesn't yet do any exhaustivity checking, but it will soon.
Yeah, speaking of that, I have so many irons in the fire I had better push this repo in case anyone else would like to work on it.
https://github.com/paulp/exhausting
It doesn't work yet but the way forward should be pretty obvious. I don't actually expect anyone else to do anything - still planning on doing it - but juuust in case.
A bit of background:
The current pattern matcher implementation is known to be buggy in several respects, including this one.Unfortunately, it's turned out to be hard to fix, so we've been working on a completely new implementation.I'm referring to the virtualizing pattern matcher, aka -Yvirtpatmat or #virtpatmat, which "virtualizes" pattern matchingusing a compilation scheme similar to for-comprehensions. (There's a fast implementation for the default matching monad, Option.)
It doesn't yet do any exhaustivity checking, but it will soon.
Note that this is an experimental feature; it's not scheduled for release just yet.