bug
bug copied to clipboard
Complementing irrefutable unapplySeq aren't recognized as exhaustive
reproduction steps
using any version of Scala
object SeqExtractor {
def unapplySeq(x: Int): Some[List[Int]] = Some(List(1))
}
1 match {
case SeqExtractor() => "zero"
case SeqExtractor(_) => "one"
case SeqExtractor(_, _, _*) => "two or more"
}
problem
SeqExtractor is irrefutable, and the three cases together are exhaustive, but we fail to recognize that.
note
Matching on List can work around that by matching on Cons or Nil exhaustively with
List(1) match { case Nil => 0 // or List() due to rewrite case head :: Nil => 1 case head :: second :: tail => 2 }
Spun out of https://github.com/scala/bug/issues/12240
I think it is also the case for regular unapply.
In my example, I was dealing with a Json AST, (sealed trait Json), and had several cases where the treatment for non-Obj was short, and for object longer.
So I added an extractor object for cosmetic reasons:
object NonObj {
def unapply(json: Json): Option[Json] = json match {
case _: Json.Obj => None
case notAnObject => Some(notAnObject)
}
}
and used it as:
def foo(json: Json): Either[Throwable, SomeClass] = json match {
case NonObj(json) => Left(MismatchError(s"$json was not '{…}'"))
case j: Json.Obj =>
// very
// long
// body
// …
}
and was surprised to see warnings like:
[warn] /home/hochgi/dev/…/src/main/scala/com/hochgi/some/path/SomeClass.scala:123:64: match may not be exhaustive.
[warn] It would fail on the following inputs: Bool(_), ByteNum(_), DoubleNum(_), FloatNum(_), IntNum(_), LongNum(_), Null, ShortNum(_), Str(_), Undefined, _
[warn] override def foo(json: Json): Either[Throwable, SomeClass] = json match {
[warn] ^
@hochgi AFAIK it doesn't peer into your extractor to see what it handles. Pattern matching is mysterious, so your question would be helpful on the forum. I don't know where these nuances are described in docs; my sense is that they try to make it "just work", with regard to warnings.
This ticket is about something entirely different.