case object gets initialized to null - how is that even possible?

I have no idea what exactly happens, but I suspect there is some kind of construction order involved. I can reproduce the problem 100% of the time, if I paste the code and do

scala> D.D1
D1: null
D2: D2
java.lang.AssertionError: assertion failed
  at scala.Predef$.assert(Predef.scala:151)
  ... 47 elided

Also if I ask for D2 first, it will fail too, so it's not related to E.

scala> D.D2
D1: D1
D2: null
java.lang.AssertionError: assertion failed
  at scala.Predef$.assert(Predef.scala:151)
  ... 47 elided

But if I ask for D first, it works 100% of the time:

scala> D
D1: D1
D2: D2
res1: D.type = D$@50434135

scala> D.D1
res2: D.D1.type = D1

I succeed to distill the problem into shorter code example:

class Bug(val f: Int) {}

object Bug {
  private def f(n: Int): Int = n

  case object Bug1 extends Bug(f(1))
  case object Bug2 extends Bug(f(2))

  val values: List[Bug] = List(Bug1, Bug2)

  println(s"1: $Bug1")
  println(s"2: $Bug2")
}

Asking for Bug.Bug1 will fail. Yet if I remove println lines - everything works. Or "execute" Bug first. Yet having values is ok.

I guess some initialisation locks go wrong way, when asking directly for Bug.Bug1 or Bug.Bug2.

Tags:

Scala