bug
bug copied to clipboard
Imprecise warning messages for non-exhaustive cases regarding List
Reproduction steps
Scala version: 2.13.8
scala> List() match { case Nil => ; case List(_) => }
^
warning: match may not be exhaustive.
It would fail on the following input: List(_)
Problem
I found that Scala 2's warning messages for non-exhaustive cases regarding List are a bit imprecise. On the other hand, Scala 3 gives better messages:
scala> List() match { case Nil => ; case List(_) => }
1 warning found
-- [E029] Pattern Match Exhaustivity Warning: ----------------------------------
1 |List() match { case Nil => ; case List(_) => }
|^^^^^^
|match may not be exhaustive.
|
|It would fail on pattern case: List(_, _, _*)
I checked Scala 2's MatchAnalysis implementation, and it seems to simply ignore unapplySeq extractors in general (and it handles only List()
as a special case). Although it wouldn't be possible to check exhaustivity for every unapplySeq extractor, checking at least List would be great, as Scala 3 already does so. Is there any plan to work on this issue?
@dwijnand this doesn't seem to be a duplicate of any existing ticket I could find. any insight here? I'm curious if it's just a problem in the message generation, or whether it's exposing some more fundamental underlying limitation in the exhaustivity checker.
No, it's just a problem in the message generation, or rather the counter-example generation. This can be our ticket for Scala 2's match analysis not being great at counter-examples based on unapplySeq arity.
Another example (unapply
not unapplySeq
):
sealed trait A
case object A1 extends A
case object A2 extends A
sealed trait T { def a: A }
object T { def unapply(t: T): Some[A] = Some(t.a) }
case class T1(x: Int) extends T { def a = A1 }
case class T2(x: Int) extends T { def a = A2 }
object Test {
def m(t: T) = t match {
case T(A1) => 0
// case T(A2) => 1
}
}
Exhaustivity can correctly identify the (in)completeness of the match, but the counter-examples in the warning message are misleading.
➜ sandbox sc Test.scala
Test.scala:10: warning: match may not be exhaustive.
It would fail on the following inputs: T1(_), T2(_)
def m(t: T) = t match {
^
1 warning