Reputation: 13783
Consider the following broken function:
def sum (list : Seq[Int]) : Int = list match {
case Nil => 0
case head :: tail => head + sum(tail)
}
Here, the function was supposed to work with a List[Int]
, but was refactored to accept Seq[Int]
instead, thus becoming broken without the compiler noticing.
This gaping hole in Scala's incomplete pattern match detection makes it next to useless.
I want to have a way of systematically detecting such problems. Specifically, I'd like the compiler to emit an error/warning on every instanceof
-guided pattern match, i.e. I only want to allow pattern matches on sealed hierarchies and on custom matchers.
Are there existing compiler options/plugins for doing conservative (as opposed to arbitrary) checks of pattern matching safety?
Upvotes: 12
Views: 1599
Reputation: 53665
Nil
and ::
are clearly ways to construct a List
, but not all Seq
uences happen to be Lists
, so one would expect the Scala type checker to reject this program as ill-typed. Right?
Wrong. Try this and you'll see what I mean:
def sum (list : Seq[Int]) : Int = list match {
case Nil => 0
case head :: tail => head + sum(tail)
case _ => -1
}
> sum(Array(1,2,3).toSeq)
res1: Int = -1
> sum(List(1,2,3))
res2: Int = 6
So you see, some Seq
uences might be able to be deconstructed with Nil
and ::
, so those which can, will. Those which can't will fail the pattern match and move on, trying the next match. Nil
and ::
are sufficient to cover all the possibilities for List
, but not for Seq
. There is a tradeoff here between subtyping, convenience, and type safety. The solution for now is: be more careful when you refactor.
Upvotes: 3
Reputation: 28680
Have a look at this answer by M. Odersky.
Checks on matches of non-sealed hierarchies are doable, not trivial and not (yet) implemented.
Upvotes: 3