If you want to see why in principle the pattern matching can be not exhaustive, for instance see the following example
trait A {
sealed trait T
case class TImpl() extends T
}
trait Fail[B <: A] {
val a: B
def foo(t : a.T): Unit = t match {
case _: a.TImpl =>
}
}
class B extends A
val b = new B
class FailImpl extends Fail[b.type] {
override val a: b.type = b
}
val fail: Fail[b.type] = new FailImpl
class C
case class CImpl() extends C with b.T
val x = CImpl()
fail.foo(x) // MatchError
You could say that actually we didn't have C
. Well, compiler should be smart enough to figure out that.
If you want to switch the warning off you can write @unchecked
def foo(t : a.T): Unit = (t: @unchecked) match {
case _: a.TImpl =>
}
According to specification,
If the selector of a pattern match is an instance of a sealed class, the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a MatchError
being raised at run-time.
https://scala-lang.org/files/archive/spec/2.13/08-pattern-matching.html#pattern-matching-expressions
Compiler can emit a warning but not must. So absence of warning doesn't guarantee that a pattern matching is exhaustive.