Currently, in Scala 2 and Dotty, forward references are handled in such a way that the code can compile yet break at runtime, cf this example of wrong vals init in an object.
Being bitten by this behavior is often a big disappointment: a typesafe language compiling should run properly, not return unexpected nulls and NullPointerException. It can also appear when someone reformat the code (and I’m not speaking of big refactoring, just changing the fields declaration order), and thus suddenly introduce some regressions seen only at runtime. This is really annoying and a trust killer.
I’ve read about the rational behind the current behavior, due to trait instantiation.
The current solution, -Xcheckinit, comes with so much performance warnings that I guess not one is willing to really use it:
It is inadvisable to use this flag outside of testing. It adds significantly to the code size by putting a wrapper around all potentially uninitialized field accesses: the wrapper will throw an exception rather than allow a null (or 0/false in the case of primitive types) to silently appear. Note also that this adds a runtime check: it can only tell you anything about code paths which you exercise with it in place.
However i hope it could be improved, essentially at compilation by disallowing illegal forward references in objects (just like Java does with the “Illegal forward reference” compiler error) and maybe even in classes (or maybe provide a warning there).
I guess it could also help when implicit resolution compiles but breaks at runtime due, again, to ordering issue, which also shows up at runtime, often rather lately, through NPE/null during Json conversions…
Tackling it a better would really enhance onboarding new developers (scala compiling but breaking at runtime isn’t exactly convincing to new comers…) as well as reduce wariness when fiddling with fields’ ordering, which should come for free in a typesafe language.
What’s your pick on the matter?
Thanks in advance