-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
vals in a nested singleton object may be initialized to null #16152
Comments
Scala 2 lacks "universal apply" and rewrites the "case apply" to "new" in refchecks. I think these init issues are a fact of life? I would expect (?) Also for the record, I can never remember |
Unfortunately, |
It turned out that Scala 2.13 has the same problem when a handmade factory method is used instead: final case class Bar(name: String)
object Bar {
object Bars {
val Name1 = Bar.make("Apple")
val Name2 = Bar.make("Banana")
val Name3 = Bar.make("Cherry")
}
def make(name: String): Bar = Bar(name)
val allBars: Seq[Bar] = {
import Bars._
Seq(Name1, Name2, Name3)
}
}
object Main2 {
def main(args: Array[String]): Unit = {
println(Bar.Bars.Name1)
println(Bar.allBars)
}
} Output (2.13.9):
I was not able to find an existing bug report for this in scala/bug. |
Sample Scala 2 issue |
@odersky how is this not a bug? surely this is not the expected behaviour. I guess fixing a bug would be an enhancement, but that doesn't mean this isn't broken behaviour. |
@robmwalsh maybe a 3rd party linter could say, "This is the expected behavior which you may not have expected." (Personally, I am on the fence. I'd prefer the language lock down cases which are obvious from a "platform" perspective.) |
@robmwalsh It is very much the expected behavior according to the rules for initialization. The reason Scala-2 does not have the behavior is that Scala-2 silently rewrites a case class So the only thing we should do is diagnose better that this is not initialization safe. |
Fair enough I guess. These initialization shenanigans are going to be a real sticking point for new users. I'm very used to the behavior from scala 2 which has never caused me any real trouble. I stumbled across this issue after getting stung by #16456 (the 2nd stack overflow case) and it's cost me another couple of days of digging through the compiler trying to figure out the cause. Diagnosing better would very much be appreciated. I've raised #16593 which will help with crash diagnosis in general, though I'm not sure about this one in particular since it will still compile (I don't actually think it should compile if it's unsound) |
FYI, @olhotak and I are still investigating a solution to this problem (One of previous attempts #12698). The challenge here is to have a solution that is simple, expressive, fast, and sound. If things go smoothly, we will propose a PR in the coming month(s). |
The problem is illustrated by the example below: ``` Scala class Foo(val opposite: Foo) case object A extends Foo(B) // A -> B case object B extends Foo(A) // B -> A ``` The check aims to be simple for programmers to understand, expressive, fast, and sound. The check is centered around two design ideas: (1) initialization-time irrelevance; (2) partial ordering. The check enforces the principle of _initialization-time irrelevance_, which means that the time when a static object is initialized should not change program semantics. For that purpose, it enforces the following rule: > **The initialization of a static object should not directly or indirectly read or write mutable state owned by another static object**. This principle not only puts the initialization of static objects on a solid foundation but also avoids whole-program analysis. Partial ordering means that the initialization dependencies of static objects form a directed-acyclic graph (DAG). No cycles with length bigger than 1 allowed --- which might lead to deadlocks in the presence of concurrency and strong coupling & subtle contracts between objects. Related Issues: #16152 #9176 #11262 scala/bug#9312 scala/bug#9115 scala/bug#9261 scala/bug#5366 scala/bug#9360
This can now be checked with the experimental option: |
Compiler version
3.0.0, 3.1.3, 3.2.0 and 3.2.2-RC1-bin-20221006-a6a3385-NIGHTLY
Minimized code
Output
Expectation
The output should be:
Replacing any of the commented part of the program above prevents the issue. Also, Scala 2.13.9 produces the expected output without any modification. So, this is a behavior change between 2.13 and 3.
The text was updated successfully, but these errors were encountered: