From abc370bf80d506e41182d0fd8344c9a925588893 Mon Sep 17 00:00:00 2001 From: Hamza Remmal Date: Thu, 11 Sep 2025 15:37:35 +0200 Subject: [PATCH] fix: correctly require a `ClassTag` when building a multidimensional `Array` [Cherry-picked 9da1fcbeef4e9dc868b0f6121708f7736cc81c94] --- compiler/src/dotty/tools/dotc/core/TypeErasure.scala | 6 ++++++ .../src/dotty/tools/dotc/typer/Applications.scala | 11 ++++------- tests/run/i23901.scala | 8 ++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 tests/run/i23901.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index f5ce7a6b4698..83fca3908836 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -386,6 +386,12 @@ object TypeErasure { case _ => false } + /** Is `tp` of the form `Array^N[T]` where T is generic? */ + def isGenericArrayArg(tp: Type)(using Context): Boolean = tp.dealias match + case defn.ArrayOf(elem) => isGenericArrayArg(elem) + case _ => isGeneric(tp) + end isGenericArrayArg + /** The erased least upper bound of two erased types is computed as follows * - if both argument are arrays of objects, an array of the erased lub of the element types * - if both arguments are arrays of same primitives, an array of this primitive diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 38d5bcf3fe9b..90cc7c9a3d84 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1282,14 +1282,11 @@ trait Applications extends Compatibility { def convertNewGenericArray(tree: Tree)(using Context): Tree = tree match { case Apply(TypeApply(tycon, targs@(targ :: Nil)), args) if tycon.symbol == defn.ArrayConstructor => fullyDefinedType(tree.tpe, "array", tree.srcPos) - - def newGenericArrayCall = + if TypeErasure.isGenericArrayArg(targ.tpe) then ref(defn.DottyArraysModule) - .select(defn.newGenericArrayMethod).withSpan(tree.span) - .appliedToTypeTrees(targs).appliedToTermArgs(args) - - if (TypeErasure.isGeneric(targ.tpe)) - newGenericArrayCall + .select(defn.newGenericArrayMethod).withSpan(tree.span) + .appliedToTypeTrees(targs) + .appliedToTermArgs(args) else tree case _ => tree diff --git a/tests/run/i23901.scala b/tests/run/i23901.scala new file mode 100644 index 000000000000..7bfcfff23551 --- /dev/null +++ b/tests/run/i23901.scala @@ -0,0 +1,8 @@ +import scala.reflect.ClassTag + +object MyArray: + def empty[T: ClassTag]: Array[Array[T]] = new Array[Array[T]](0) + +@main def Test = + val arr: Array[Array[String]] = MyArray.empty[String] + assert(arr.length == 0)