Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@static initialization order is brittle #6351

Closed
scabug opened this issue Sep 10, 2012 · 4 comments
Closed

@static initialization order is brittle #6351

scabug opened this issue Sep 10, 2012 · 4 comments
Milestone

Comments

@scabug
Copy link

scabug commented Sep 10, 2012

rk:test rkuhn$ cat static.scala 
import annotation.static

object Static {

  val i1 = { println("i1"); 1 }
  val l1 = { println("l1"); 1l }
  @static val si1 = { println("si1"); i1 }
  @static val sl1 = { println("sl1"); l1 }
  println("sl1=" + sl1)

  def main(args: Array[String]) {}
}
rk:test rkuhn$ scalac static.scala 
rk:test rkuhn$ scala Static
si1
i1
l1
sl1=0
sl1

What this means is that saying “static fields are initialized first” can easily be subverted, and the fact is not blatantly visible in the code. It is one of those things where you need to read the whole class to find out in which order things will run.

Given how the two kinds of initialization code live in the same lexical space, it would be much better if initialization would also proceed linearly, following the lexical structure. One possibility to do this would be to have the static initializer block run the whole thing and compute the values to be put into all fields of the MODULE instance, and then these values are passed in as constructor arguments. The down-side would be that “this” is not available. I’d rather have this restriction (and require a @static annotation on the object itself) than erratic initialization order changes (which might not even be known at compile time). Semantics of a missing @static annotation on the object could then be to run the whole initialization within the MODULE constructor, giving you “this” but taking away finality of static fields.

@scabug
Copy link
Author

scabug commented Sep 10, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6351?orig=1
Reporter: @rkuhn
Affected Versions: 2.10.0-M7

@scabug
Copy link
Author

scabug commented Sep 10, 2012

@rkuhn said:
There is an added twist to this when pairing @static with App:

rk:test rkuhn$ cat static.scala 
import annotation.static

object Static extends App {
  val i = 1
  @static val si1 = { println("si1"); i }
  println("si1=" + si1)
}
rk:test rkuhn$ scalac static.scala 
rk:test rkuhn$ scala Static
si1
si1=0

The thing here is that there is no way to get it “right” in this case, because the initialization code of the “final” (only not in bytecode) “val i” runs outside of the context of class initialization. Given that it cannot work, this must be a compile time error.

@scabug
Copy link
Author

scabug commented Sep 11, 2012

@gkossakowski said:
This inspired me to come up with this:

object A {
  @static val x = y
  val y = 10
}

object Main {
  def main(args: Array[String]): Unit = {
    println(A.x)
  }
}

this will print 10 as expected. Now put @static in front of y:

object A {
  @static val x = y
  @static val y = 10
}

and you'll get 0 printed.

@scabug
Copy link
Author

scabug commented Oct 25, 2012

@gkossakowski said:
This ticket should be closed. @static has been removed before we went for RC cycle of 2.10:
scala/scala#1340

@scabug scabug closed this as completed Oct 25, 2012
@scabug scabug added this to the 2.10.0 milestone Apr 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant