[WIP] Scala with Explicit Nulls

While the work is still in process for better interoperability with Java & easier migration of legacy code, I’m wondering if it is good and possible to only produce warnings for null-related type errors?

I conjecture that warnings instead of errors will make the system more friendly to programmers and make migration of legacy code easier.

In the compiler, type mismatches are usually reported as errors. However, it seems some small tweak is possible to report warnings for null-related type mismatches.

Hundreds of warnings are not programmer friendly, what’s needed is a way to turn on/off the checks, perhaps with a language import.

Project-level and source-file level language feature switches are definitely helpful, AFAIK they are planned. Even with all these switches, I still think warnings are better than errors.

Warnings are not acceptable here, because nullability being part of the type means that it will have to be taken into account for overload resolution and implicit search. Different results can be obtained successfully, rather than one failure which could be reported as a warning.

No, anything that changes the type of things in a way that is visible to ad hoc polymorphism must report errors on failure.

2 Likes

We already loosen the typing rule by allowing selection on T | JavaNull for usability. I conjecture there are more places that we could report warnings instead of errors without impacting overload resolution and implicit search.

To some extent, we already embrace the idea that typing errors related to null should be suppressed for friendliness (e.g. selection on T | JavaNull). A natural extension of the idea is to report warnings instead errors in more places. How to do this in more places seems to be a matter of technical detail.

I think the difference here, w.r.t. other cases which would be reported as errors from now on is that these cases stem from three causes:

  • You’re doing something improper within your own code.
  • You’re doing something improper while using an explicit-null Scala library.
  • You’re doing something improper while using a pre-explicit-null Scala library.

In case 1, you have full control over it and you must fix it.
In case 2, you have the case that you’re using a library that had its nullness laid out explicitly (although maybe not as intended, e.g. forgot a |Null for a parameter. You can work around that, maybe file an issue.
In case 3, you’ll wait for the library to move to e-null, and for parameters, (2) may partially apply.

Now with Java, you are on a different level (unless you work in a mixed-source codebase): You use a library that you do not have control over, and that doesn’t support any kind of explicit-null. Yes, the Checker Framework and similar tools exist (and it seems explicit-null might take advantage of that), but they are optional. If and once explicit-null lands, it’s there and it will stay. Scala on that version won’t work without the nullabilities anymore, but for Java and its tools, that won’t ever be the case. Hence relaxing for usability there, and only there, seems to be the right decision for me.

1 Like

I think this is something we should consider only if the migration turns out to be too painful/impossible when explicit nulls cause errors. We’ll have a better idea on this as we migrate the standard library and others in the community build (we’re currently working on this).

In my experience (albeit in other languages) warnings tend to be ignored, particularly if there are lots of them (which is the hypothetical that motivates the warnings-instead-of-errors approach in the first place).

Additionally, it looks like many projects use “-Xfatal-warnings” (https://github.com/search?l=Scala&q=-Xfatal-warnings&type=Code), so if indeed that particular flag is popular warnings won’t help.

4 Likes

An option to get warnings will still help, especially in big codebases. Those projects can still drop -Xfatal-warnings when migrating to a new Scala version, especially one with so many changes, and finally get to -Xfatal-warnings. The quickest you get to something that compiles and runs with the new compiler, the quicker you can test if the code still works or you made a mistake, and start addressing a few warnings at a time.

1 Like

@abeln : What will this mean for Some(null)?

And if that’s going away, what will it mean for optimizing Option in general. I think there were efforts to do just that but Some(null) made it impossible.

Nothing. The type of Some(null) is still Some[Null]. And it can be assigned to an Option[String | Null] but not an Option[String].

5 Likes

Are there any plans for an import statement for -Yexplicit-nulls, similar to import scala.language.strictEquality?

P.S.: I have the same question for -Ysafe-init.

No, that is not possible. Explicit nulls transform the type system itself. That must be done globally or not at all.

2 Likes

-Yexplicit-nulls is global but unsafeNulls can be scoped under an import. See the doc page: Explicit Nulls | Scala 3 Language Reference | Scala Documentation

-Ysafe-init enables warnings globally but warnings can be suppressed locally using @unchecked. Doc page: Safe Initialization | Scala 3 Language Reference | Scala Documentation

2 Likes