Scala: Cannot check match for unreachable even with default
I am working on a compiler for a simple language for a course and I came across this warning. The pattern matching in the question is simple, so I don't understand why this pops up. Here's the relevant template:
(tcExpr(lhs), tcExpr(rhs)) match {
case (TInt, TInt) | (TString, TString) | (TBoolean, TBoolean) | (TIntArray, TIntArray) | (TObject(_), TObject(_)) => TBoolean
case _ => TError
with tcExpr signatures that are def tcExpr(expr: ExprTree, expected: Type*): Type
, ExprTree
representing the expression, and Type
are case objects. All except TObject()
are simple objects and TObject()
take a symbol representing the class as an argument.
What I don't understand is that there are not many such possibilities. Why can't the compiler figure it out? Is there something I forgot or misunderstood?
Thanks a lot for your answers,
Nicholas
source to share
I could reproduce the "warning: cannot match for unreachable". with the following code (I don't know how many types you have. I took 32 + 1 as the upper bound):
trait Type
case object T0 extends Type
case object T1 extends Type
case object T2 extends Type
case object T3 extends Type
case object T4 extends Type
...
<generated code, 32 types in total>
...
case object T31 extends Type
def foo: Type = T0
(foo, foo) match {
case (T0,T0) | <total 32 types> | (T31,T31) => println("true")
case _ => println("false")
}
It looks like the reason is that it just runs out of memory trying to check all possible cases. The recommendation provided by the warning is to add an option -Dscalac.patmat.analysisBudget=off
when the compiler starts. Just tried to compile this parameter: it works, no more warnings.
EDIT . It just turned out that without using the bisection option, s> = 5 types stop working. It really isn't that much.
My suggestion would be to simply remove the ever-long enum and replace it with a short and concise equation:
(foo, foo) match {
case (Obj(_), Obj(_)) => println("true")
case (x, y) if (x == y) => println("true") // Order is important, thx @Nico
case _ => println("false")
}
Then the warning disappears and the code stops spilling over 80 characters / limit.
source to share