This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Guarded Match Exhaustiveness Testing

2 replies
Jon Shea
Joined: 2012-01-06,
User offline. Last seen 42 years 45 weeks ago.

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

moors
Joined: 2010-10-06,
User offline. Last seen 36 weeks 4 days ago.
Re: Guarded Match Exhaustiveness Testing
The short story: I agree that would be good to have, and we're planning to implement this in the "alternative" pattern matcher soon.It's probably not going to be fixed in the current pattern matcher, though.

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.
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
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.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland