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

+3


source to share


1 answer


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.

+1


source







All Articles