[WIP] Scala with Explicit Nulls

Hello,

Thanks a lot for your efforts. This is a really hard problem, and I’m glad it’s been tackled to that depth. When I first saw the idea of the T | JavaNull, I said it was the first design I’d seen that had a chance not to crash and burn; the last time I said something like that, @odersky replied: “[Coming from you], I take that as strong endorsement.”

Obviously, I have quite a number of comments :smile:

Equality (ref in doc)

Because of the unsoundness, we need to allow comparisons of the form x == null or x != null even when x has a non-nullable reference type (but not a value type). This is so we have an “escape hatch” for when we know x is nullable even when the type says it shouldn’t be.

I disagree with that reasoning, for two reasons:

  • a normal program never tests whether a val x = something is in fact null to test around initialization problems. This is a false problem, it shouldn’t be tackled.
  • there is already an escape hatch if someone really really wants to do that: (x: T | Null) == null

That said, you can’t prevent anyone from ever doing x == null regardless of the type of x, because == is defined on Any, so this whole thing is quite moot anyway. It’s possible to warn when trying to compare a non-nullable type with null, though, like scalac already does for primitive types:

Welcome to Scala 2.12.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.

scala> val x: Int = 5
x: Int = 5

scala> x == null
<console>:13: warning: comparing values of types Int and Null using `==' will always yield false
       x == null
         ^
res0: Boolean = false

Similarly, I think the section on Reference equality is biased by the same above false issue. Here it’s even more annoying because you have to add an entirely new top-type, that is magical, in the type system. I strongly suggest to remove all of that. I can use x == null instead of x eq null anyway, if I want to do that! And yes, == null is always as efficient as eq null, so performance is not a good excuse either.

Working with Null (ref in doc)

x.nn, as a method name, does not follow established conventions for methods in the Scala library: alphanumeric method names should be full words, not initials (eq and ne are unfortunate precedents, but let’s not exacerbate the issue). This is one of the cases where I would recommend a symbolic operator, such as x.!!. Otherwise, spell out x.ensureNotNull or something like that.

In addition, for both the above method, and the implicit conversions that you mention below, I strongly suggest that they be hidden behind an import, such as

import scala.NullInterop._

I could live with x.!! always in scope, but please don’t put unsound implicit conversions in scope for every program, every time.

Nullification function (ref in doc)

I am confused why nf(A | B) and nf(A & B) need to be defined. IIRC, nf is only applied to types loaded from Java source files and Java-generated class files, and those would never contain | or & types. Can you elaborate on an example where this is relevant?

JavaNull (ref in doc)

I agree with @smarter’s comment on the PR that it is problematic that we cannot write down a JavaNull type in the source code. I fail to see any advantage to that restriction. Can we simply lift it?

Flow-sensitive inference (ref in doc)

Although I sympathize with the issue that this feature addresses, I can’t help but have a bad feeling about it. There is no precedent in Scala for anything like that, and I am wary of adding it as part of such an important change. I believe pattern matching should be enough to safely deconstruct nullable types.

Besides, if we really want this, I find it very odd that it only supports null. I would expect it to support other idioms, such as

if (x.isInstanceOf[Foo]) {
  val y: Foo = x // typechecks because I know `x` is a `Foo`
}

At the very least, I believe that this flow-sensitive inference should be presented as an orthogonal proposal. Fundamentally, it has nothing to do with non-nullable types.

That’s all for today :wink: Thanks again for all your hard work. I hope we can get this all the way to the finish line.

13 Likes