Skip to content

Commit 803f324

Browse files
authored
Merge pull request #4046 from dotty-staging/fix-#4037
Fix #4037: Fix code generation for generic arrays
2 parents 4cfffbe + 32787a4 commit 803f324

File tree

5 files changed

+22
-4
lines changed

5 files changed

+22
-4
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
372372
ref(defn.DottyArraysModule).select(defn.newArrayMethod).withPos(pos)
373373

374374
if (!ctx.erasedTypes) {
375-
assert(!TypeErasure.isUnboundedGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray
375+
assert(!TypeErasure.isGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray
376376
newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos)
377377
} else // after erasure
378378
newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos)

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

+10
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ object TypeErasure {
216216
case _ => false
217217
}
218218

219+
/** Is `tp` an abstract type or polymorphic type parameter, or another unbounded generic type? */
220+
def isGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match {
221+
case tp: TypeRef => !tp.symbol.isClass
222+
case tp: TypeParamRef => true
223+
case tp: TypeProxy => isGeneric(tp.underlying)
224+
case tp: AndType => isGeneric(tp.tp1) || isGeneric(tp.tp2)
225+
case tp: OrType => isGeneric(tp.tp1) || isGeneric(tp.tp2)
226+
case _ => false
227+
}
228+
219229
/** The erased least upper bound is computed as follows
220230
* - if both argument are arrays of objects, an array of the erased lub of the element types
221231
* - if both arguments are arrays of same primitives, an array of this primitive

compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ class ArrayConstructors extends MiniPhase {
4646
val cs = tp.tpe.widen.classSymbol
4747
tree.fun match {
4848
case Apply(TypeApply(t: Ident, targ), dims)
49-
if !TypeErasure.isUnboundedGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) =>
49+
if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) =>
5050
rewrite(targ.head.tpe, dims)
5151
case Apply(TypeApply(t: Select, targ), dims)
52-
if !TypeErasure.isUnboundedGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) =>
52+
if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) =>
5353
Block(t.qualifier :: Nil, rewrite(targ.head.tpe, dims))
5454
case _ => tree
5555
}

compiler/src/dotty/tools/dotc/typer/Applications.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
831831
.select(defn.newGenericArrayMethod).withPos(tree.pos)
832832
.appliedToTypeTrees(targs).appliedToArgs(args)
833833

834-
if (TypeErasure.isUnboundedGeneric(targ.tpe))
834+
if (TypeErasure.isGeneric(targ.tpe))
835835
newGenericArrayCall
836836
else tree
837837
case _ =>

tests/run/i4037.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.reflect.ClassTag
2+
3+
object Test {
4+
def foo[T <: AnyRef : ClassTag] = new Array[T](42)
5+
def main(args: Array[String]): Unit = {
6+
val x: Array[String] = foo[String]
7+
}
8+
}

0 commit comments

Comments
 (0)