Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 4 additions & 7 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1427,14 +1427,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
Expand Down
8 changes: 8 additions & 0 deletions tests/run/i23901.scala
Original file line number Diff line number Diff line change
@@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe test the runtime class?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well to assert that it is specialised based on the classtag

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this fix, we couldn't even create the array in Line 7, this is a run test witnessing that we are indeed creating the array correctly. Also, dotty will add a call to asInstanceOf[Array[Array[String]]] here which is enough to assert that the right array is created. Also note that asInstanceOf was what indicated that something was really wrong it the generated code.

Loading