An Experiment to Cheer For: Safe Initialization

Mark "Justin" Waks
2 min readDec 17, 2019

--

A few days ago, I mentioned that the Dotty master now has support for explicit null values — a big win for type safety in Scala. Not quite so far along, and much subtler, but arguably as important, is this related PR from Fengyun and others, introducing safe initialization. (More details can be found in this gist.)

They are trying to address a wart in the Scala language that takes almost everybody by surprise at some point in their career. The thing is, values are typically set to null before they are initialized to a more concrete value. This window tends to be brief in well-designed code, and is usually invisible, but sometimes (especially when subtyping is involved) you can wind up with a NullPointerException that just leaves you scratching your head.

One of the examples they give in the PR looks like this:

abstract class AbstractFile {
def name: String
val extension: String = Path.extension(name)
}

class RemoteFile(url: String) extends AbstractFile {
val localFile: String = url.hashCode + ".tmp"
def name: String = localFile
}

All of this code looks innocuous, especially in isolation. But in fact it will crash when you try to construct a RemoteFile, because:

  • extension requires name;
  • name requires localFile;
  • localFile isn’t defined yet when we’re setting up extension.

So the constructor for RemoteFile will throw an NPE in Scala 2. (To see the problem in action, see this fiddle.)

There are ways to work around these problems (typically by changing a val to a lazy val or def), but the point is, you currently don’t find out that there is a problem until it crashes at runtime — usually with a confusing NPE.

The current PR adds a new -Ycheck-init flag on the compiler, which tries to detect this sort of situation and report the use of a “non-initialized field value”. The examples they show are very promising: the error messages provide, at compile time, the breadcrumbs you need in order to understand what’s going on and fix it. (It might be improved if the error provided suggestions of how to fix it, which would help novices, but one thing at a time.)

The usual caveats apply: this is just a PR, not in Dotty master yet, much less approved for Scala 3, and it’s still an experiment behind a compiler flag. But if they don’t find any critical problems, this seems like a big win for the language, helping with a mildly common and confusing category of bug. I expect I would routinely turn this flag on, and I really hope it makes its way into Scala 3…

--

--

Mark "Justin" Waks
Mark "Justin" Waks

Written by Mark "Justin" Waks

Lifelong programmer and software architect, specializing in online social tools and (nowadays) Scala. Architect of Querki (“leading the small data revolution”).

No responses yet