bug icon indicating copy to clipboard operation
bug copied to clipboard

Complementing irrefutable unapplySeq aren't recognized as exhaustive

Open martijnhoekstra opened this issue 5 years ago • 2 comments

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

martijnhoekstra avatar Nov 28 '20 10:11 martijnhoekstra

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 avatar Apr 07 '22 16:04 hochgi

@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.

som-snytt avatar Apr 07 '22 18:04 som-snytt