In attempt to single out the “match may not be exhaustive” warning, I ended up with a simpler and more precise example:
// --- uncomment this:
final class Foo[A] {}
def foo[A] = new Foo[A]
// --- or this:
//abstract sealed class Foo[A] {}
//def foo[A] = new Foo[A] {}
// --- END
def alwaysOk1(foos: List[Foo[Any]]): Unit = foos match {
case (foo: Foo[?]) :: _ => ()
case Nil => ()
}
def warnsForNonSealedOnly1(foos: List[Foo[?]]): Unit = foos match {
case (foo: Foo[?]) :: _ => ()
case Nil => ()
}
def alwaysOk2(foo: Option[Foo[Any]]): Unit = foo match {
case Some(foo: Foo[?]) => ()
case None => ()
}
def warnsForNonSealedOnly2(foo: Option[Foo[?]]): Unit = foo match {
case Some(foo: Foo[?]) => ()
case None => ()
}
def alwaysOk3(t: ((Int, (Foo[?], String)), Double)): Unit = t match {
case ((a, (foo: Foo[?], b)), c) => ()
}
I.e. the warning emerges on Scala 2 only (both 2.13 and 2.12) and only if all three conditions are met:
Foo
is a non-sealed class. It can be either abstract or concrete though – it doesn’t matter.Foo
is passed with a whildcard?
, notAny
.- There’s a switch between two or more cases involved in the
match
expression, not just extraction of values or types.
The presense of type extraction doesn’t matter, actually – type whildcards lead to the same result.
I wonder if it makes sense to report it to scala/bug? I see there are a lot of other issues regarding false “match may not be exhaustive” warning, but couldn’t find one that would have sealed/non-sealed dichotomy involved.