bug icon indicating copy to clipboard operation
bug copied to clipboard

Case classes with ~100 fields synthesize equals method that is stack intensive to typecheck

Open scabug opened this issue 10 years ago • 1 comments

Since Scala 2.11.0, case classes can have an arbitrary number of fields (well, up to JVM limits which I believe is ~256).

However, these newly unleached gargantuan classes can easily trigger a StackOverflowError in type checker. Actually, it seems to happen in erasure phases typechecker first, perhaps that is more stack hungry at each level of recursion.

The troublesome expression is the expression: field1.==(other.field1).&&(field2 == other.field2).&& ....

We could break this up into group of, say, 32 fields:

val result = false
result ||= field1.==(other.field1).&&(field2 == other.field2).&& ..
if (!result) return false
result ||= field33.==(other.field33).&&(field34 == other.field34).&& ..
...

Workaround is to increase the stack size of the compiler, or to refactor the code to avoid such big classes. While we recommend the latter option as a matter of good style, we shouldn't forget that case classes might be the result of code generators.

Another workaround is to manaully define the equals method.

case class Gargantuan(f1: T1, ... f100: T100) {
  override def equals(other: Any) = other match {
    case g: Gargantuan => g.productIterator.toList == productIterator.toList
    case _ => false
  }

The compiler could choose to emit this once N passed some threshold, too, although we might not want to incur the boxing penalty.

scabug avatar Mar 02 '15 11:03 scabug

Imported From: https://issues.scala-lang.org/browse/SI-9193?orig=1 Reporter: @retronym Affected Versions: 2.11.5

scabug avatar Mar 02 '15 11:03 scabug