Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6fe3520

Browse files
authored
Merge pull request #11165 from lrytz/pr11021-revert
Re-introduce null checks to ScalaRunTime.wrapXArray
2 parents 0576852 + 1af76c7 commit 6fe3520

4 files changed

Lines changed: 44 additions & 16 deletions

File tree

src/library/scala/runtime/ScalaRunTime.scala

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -280,20 +280,23 @@ object ScalaRunTime {
280280
case s => s + "\n"
281281
}
282282

283-
// Convert arrays to immutable.ArraySeq for use with Scala varargs.
284-
// By construction, calls to these methods always receive a fresh (and non-null), non-empty array.
285-
// In cases where an empty array would appear, the compiler uses a direct reference to Nil instead.
286-
// Synthetic Java varargs forwarders (@annotation.varargs or varargs bridges when overriding) may pass
287-
// `null` to these methods; but returning `null` or `ArraySeq(null)` makes little difference in practice.
288-
def genericWrapArray[T](xs: Array[T]): ArraySeq[T] = ArraySeq.unsafeWrapArray(xs)
289-
def wrapRefArray[T <: AnyRef](xs: Array[T]): ArraySeq[T] = new ArraySeq.ofRef[T](xs)
290-
def wrapIntArray(xs: Array[Int]): ArraySeq[Int] = new ArraySeq.ofInt(xs)
291-
def wrapDoubleArray(xs: Array[Double]): ArraySeq[Double] = new ArraySeq.ofDouble(xs)
292-
def wrapLongArray(xs: Array[Long]): ArraySeq[Long] = new ArraySeq.ofLong(xs)
293-
def wrapFloatArray(xs: Array[Float]): ArraySeq[Float] = new ArraySeq.ofFloat(xs)
294-
def wrapCharArray(xs: Array[Char]): ArraySeq[Char] = new ArraySeq.ofChar(xs)
295-
def wrapByteArray(xs: Array[Byte]): ArraySeq[Byte] = new ArraySeq.ofByte(xs)
296-
def wrapShortArray(xs: Array[Short]): ArraySeq[Short] = new ArraySeq.ofShort(xs)
297-
def wrapBooleanArray(xs: Array[Boolean]): ArraySeq[Boolean] = new ArraySeq.ofBoolean(xs)
298-
def wrapUnitArray(xs: Array[Unit]): ArraySeq[Unit] = new ArraySeq.ofUnit(xs)
283+
// Convert an array to an immutable.ArraySeq for use with Scala varargs.
284+
// `foo(x, y)` is compiled to `foo(wrapXArray(Array(x, y))).
285+
// For `foo()`, the Scala 2 compiler uses a reference to `Nil` instead; Scala 3 doesn't have this special case.
286+
//
287+
// The `null` checks are there for backwards compatibility. They were removed in 2.13.17 (scala/scala#11021)
288+
// which led to a ticket in Scala 3 (scala/scala3#24204). The argument may be null:
289+
// - When calling a Scala `@varargs` method from Java
290+
// - When using an array as sequence argument in Scala 3: `foo((null: Array[X])*)`
291+
def genericWrapArray[T](xs: Array[T]): ArraySeq[T] = if (xs ne null) ArraySeq.unsafeWrapArray(xs) else null
292+
def wrapRefArray[T <: AnyRef](xs: Array[T]): ArraySeq[T] = if (xs ne null) new ArraySeq.ofRef[T](xs) else null
293+
def wrapIntArray(xs: Array[Int]): ArraySeq[Int] = if (xs ne null) new ArraySeq.ofInt(xs) else null
294+
def wrapDoubleArray(xs: Array[Double]): ArraySeq[Double] = if (xs ne null) new ArraySeq.ofDouble(xs) else null
295+
def wrapLongArray(xs: Array[Long]): ArraySeq[Long] = if (xs ne null) new ArraySeq.ofLong(xs) else null
296+
def wrapFloatArray(xs: Array[Float]): ArraySeq[Float] = if (xs ne null) new ArraySeq.ofFloat(xs) else null
297+
def wrapCharArray(xs: Array[Char]): ArraySeq[Char] = if (xs ne null) new ArraySeq.ofChar(xs) else null
298+
def wrapByteArray(xs: Array[Byte]): ArraySeq[Byte] = if (xs ne null) new ArraySeq.ofByte(xs) else null
299+
def wrapShortArray(xs: Array[Short]): ArraySeq[Short] = if (xs ne null) new ArraySeq.ofShort(xs) else null
300+
def wrapBooleanArray(xs: Array[Boolean]): ArraySeq[Boolean] = if (xs ne null) new ArraySeq.ofBoolean(xs) else null
301+
def wrapUnitArray(xs: Array[Unit]): ArraySeq[Unit] = if (xs ne null) new ArraySeq.ofUnit(xs) else null
299302
}

test/files/run/pr11021/J.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public class J {
2+
public static int m() {
3+
String[] arg = null;
4+
return Test.va(arg);
5+
}
6+
}

test/files/run/pr11021/Test.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
object Test {
2+
@annotation.varargs def va(s: String*) =
3+
if (s == null) 0
4+
else 1
5+
6+
def main(args: Array[String]) = {
7+
val arr: Array[String] = null
8+
val seq: Seq[String] = null
9+
10+
assert(va(arr: _*) == 0): @annotation.nowarn("cat=deprecation")
11+
assert(va(seq: _*) == 0)
12+
assert(J.m() == 0)
13+
}
14+
}

test/junit/scala/runtime/ScalaRunTimeTest.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,9 @@ class ScalaRunTimeTest {
6262
assertEquals(null, stringOf(tpolecat))
6363
assertEquals("null toString", replStringOf(tpolecat, 100))
6464
}
65+
66+
@Test def scala3ticket24204(): Unit = {
67+
assertEquals(null, ScalaRunTime.wrapRefArray(null: Array[String]))
68+
assertEquals(null, ScalaRunTime.genericWrapArray(null: Array[String]))
69+
}
6570
}

0 commit comments

Comments
 (0)