Skip to content

Chaining Java functions using -Yexplicit-nulls and scala.language.unsafeNulls fails compilation  #14592

Closed
@martingd

Description

@martingd

Compiler 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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions