Chaining Java functions using `-Yexplicit-nulls` and `scala.language.unsafeNulls` fails compilation
See original GitHub issueCompiler version
Scala 3.1.1
Minimized code
Compiling this code with compiler option -Yexplicit-nulls
results in a compilation error:
import scala.language.unsafeNulls
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
val x = Files.getFileStore(Paths.get("")).name
val y = Thread.currentThread.getContextClassLoader
Output
The result of compiling the above code:
% scala3-compiler -version
Scala compiler version 3.1.1 -- Copyright 2002-2022, LAMP/EPFL
% scala3-compiler -Yexplicit-nulls test.scala
-- Error: test.scala:7:8 -------------------------------------------------------
7 |val x = Files.getFileStore(Paths.get("")).name
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|undefined: java.nio.file.Files.getFileStore(
| java.nio.file.Paths.get("", [ : String | Null]*)
|).name # -1: TermRef(OrType(TypeRef(ThisType(TypeRef(NoPrefix,module class file)),class FileStore),TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Null)),name) at sbt-api
-- Error: test.scala:8:8 -------------------------------------------------------
8 |val y = Thread.currentThread.getContextClassLoader
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|undefined: Thread.currentThread().getContextClassLoader # -1: TermRef(OrType(TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class Thread),TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Null)),getContextClassLoader) at sbt-api
2 errors found
Expectation
The code should compile without error.
Additional comments
When compiling the above code, the compiler emits two errors. The error is only triggered when using compiler option -Yexplicit-nulls
and also including import scala.language.unsafeNulls
in the scope of the lines that fail compilation.
Any call to a Java function (returning T | Null
for some type T
) that is chained from a call to another Java function triggers this condition.
Making a similar chain of functions using code defined in Scala, like in the code below, does not trigger the compiler error:
import scala.language.unsafeNulls
object X:
def f: Y | Null = ???
class Y:
def g: Z | Null = ???
class Z
val z = X.f.g
Adding explicit .nn
calls in the failing code works around the bug – with import scala.language.unsafeNulls
still in place.
For example, this code compiles without error:
import scala.language.unsafeNulls
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
val x = Files.getFileStore(Paths.get("")).nn.name
val y = Thread.currentThread.nn.getContextClassLoader
Another workaround is to split the chained calls as the bug is only triggered when chaining calls. This code compiles:
import scala.language.unsafeNulls
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
val x = Files.getFileStore(Paths.get(""))
val xx = x.name
val y = Thread.currentThread
val yy = y.getContextClassLoader
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (2 by maintainers)
Top GitHub Comments
The fix, to “thread context” correctly, puns on this example,
Thread.currentThread.getContextClassLoader
. A test could prove quite punning.Duplicate of issue https://github.com/lampepfl/dotty/issues/14319.