Skip to content

Match Exhaustiveness Testing Ignores Guard Statements #5365

Closed
scala/scala
#9140
@scabug

Description

@scabug

It seems that guarded match expressions are not tested for completeness at compile time. Or, more accurately, it seems that guarded case statements are optimistically considered complete. 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 = <fun>

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 noop unguarded match. Why don't we give Scala users the option for added safety?

Metadata

Metadata

Labels

fixed in Scala 3This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/)has PRhelp wantedpatmat

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions