Skip to content

Regression for unpacking var-arg splices when using Scala 2.13.17 #24204

@WojciechMazur

Description

@WojciechMazur

It's no longer possible to guard against null var arg splice in the receiver method. The vararg == null is ignored.
The problem exists when using Scala 3 (using any version) with Scala 2.13.17 stdlib.
Effectively there is no way to detect null splice:

  • _ != null is ignored
  • _.length > 0 results in java.lang.NullPointerException: Cannot read the array length because the return value of "scala.collection.immutable.ArraySeq$ofRef.unsafeArray()" is null
  • Option(_).isDefined evaluates to true (becouse of the null check)

Based on failures in scalatest/scalatest in #24190

Compiler version

All Scala versions, tested: 3.3.7 LTS, 3.7.4-RC1, 3.8.0-RC1-bin-20251017-96aff06-NIGHTLY

Minimized code

class NullArgumentException(msg: String) extends IllegalArgumentException(msg)

trait Suite
class Suites(suitesToNest: Suite*) {
  if suitesToNest == null then
    throw NullArgumentException("The passed suites splice is null")

  for
    s <- suitesToNest // triggers NullPointerException
    if s == null
  do
    throw new NullArgumentException("One of the passed suite was null")
}

@main def Test = {
  val aNull: Array[Suite] = null
  try {
    new Suites(aNull*)
    throw IllegalStateException("Should not be reached")
  } catch {
    case ex: NullArgumentException => println(s"ok, expected: $ex")
  }
}

Output

// scala test.scala  -S 3.7.4-RC1 --dep org.scala-lang:scala-library:2.13.17 
Exception in thread "main" java.lang.NullPointerException
        at java.base/java.lang.reflect.Array.getLength(Native Method)
        at scala.collection.ArrayOps$ArrayIterator.<init>(ArrayOps.scala:126)
        at scala.collection.immutable.ArraySeq$ofRef.iterator(ArraySeq.scala:348)
        at scala.collection.View$Filter.iterator(View.scala:144)
        at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:629)
        at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:628)
        at scala.collection.AbstractIterable.foreach(Iterable.scala:936)
        at scala.collection.IterableOps$WithFilter.foreach(Iterable.scala:906)
        at Suites.<init>(test.scala:9)
        at test$package$.Test(test.scala:18)
        at Test.main(test.scala:15)

Same problem in nightly which ships it's own stdlib

// scala test.scala  -S 3.nightly
Compiled project (Scala 3.8.0-RC1-bin-20251018-96aff06-NIGHTLY, JVM (21))
Exception in thread "main" java.lang.NullPointerException
        at java.base/java.lang.reflect.Array.getLength(Native Method)
        at scala.runtime.ScalaRunTime$.array_length(ScalaRunTime.scala:89)
        at scala.collection.ArrayOps$ArrayIterator.<init>(ArrayOps.scala:129)
        at scala.collection.immutable.ArraySeq$ofRef.iterator(ArraySeq.scala:351)
        at scala.collection.View$Filter.iterator(View.scala:149)
        at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:632)
        at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:337)
        at scala.collection.AbstractIterable.foreach(Iterable.scala:946)
        at scala.collection.IterableOps$WithFilter.foreach(Iterable.scala:916)
        at Suites.<init>(test.scala:9)
        at test$package$.Test(test.scala:18)
        at Test.main(test.scala:15)

Expectation

Same behaviour as when using 2.13.16 stdlib

// scala test.scala  -S 3.7.4-RC1 --dep org.scala-lang:scala-library:2.13.16
Compiled project (Scala 3.7.4-RC1, JVM (21))
[hint]  "scala-library is outdated, update to 2.13.17"
     scala-library 2.13.16 -> org.scala-lang:scala-library:2.13.17
ok, expected: NullArgumentException: The passed suites splice is null

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions