From 442e6a09eae30c22aad559ecf520713056e86cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Wed, 18 Dec 2024 13:52:59 +0100 Subject: [PATCH] Fix #22226: Use `classOf[BoxedUnit]` for Unit array in `ArrayConstructors`. The `ArrayConstructors` phase rewrites array constructors to calls to `scala.runtime.Arrays.newArray`. When it does that, it must pass the run-time `jl.Class` of the element type. Previously, it used `classOf[Unit]` when creating an `Array[Unit]` (or nested). That is not correct, as from the Java perspective, we need to create `Array[BoxedUnit]`. We now identify `elemType <: Unit` and replace it with `BoxedUnit`. --- This highlights a limitation of the Scala.js backend. We should rewrite calls to `newArray` in the backend to use direct array creation instead. --- .../tools/dotc/transform/ArrayConstructors.scala | 5 ++++- .../testsuite/compiler/RegressionTestScala3.scala | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala index e94fa612e6cf..84cb64533532 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala @@ -27,7 +27,10 @@ class ArrayConstructors extends MiniPhase { override def transformApply(tree: tpd.Apply)(using Context): tpd.Tree = { def expand(elemType: Type, dims: List[Tree]) = - tpd.newArray(elemType, tree.tpe, tree.span, JavaSeqLiteral(dims, TypeTree(defn.IntClass.typeRef))) + val elemTypeNonVoid = + if elemType.isValueSubType(defn.UnitType) then defn.BoxedUnitClass.typeRef + else elemType + tpd.newArray(elemTypeNonVoid, tree.tpe, tree.span, JavaSeqLiteral(dims, TypeTree(defn.IntClass.typeRef))) if (tree.fun.symbol eq defn.ArrayConstructor) { val TypeApply(tycon, targ :: Nil) = tree.fun: @unchecked diff --git a/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala b/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala index de260f3481ed..02cb08789232 100644 --- a/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala +++ b/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala @@ -145,6 +145,17 @@ class RegressionTestScala3 { assertEquals(5, Issue14289.Container.b()) assertEquals(true, Issue14289.Container.c()) } + + @Test def createArrayOfUnitIssue22226(): Unit = { + val a = Array.ofDim[Unit](0) + assertSame(classOf[Array[Unit]], a.getClass()) + + val b = new Array[Unit](0) + assertSame(classOf[Array[Unit]], b.getClass()) + + val c = Array.ofDim[Unit](0, 0) + assertSame(classOf[Array[Array[Unit]]], c.getClass()) + } } object RegressionTestScala3 {