diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 53609219ba01..916cb2df69ee 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -372,7 +372,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { ref(defn.DottyArraysModule).select(defn.newArrayMethod).withPos(pos) if (!ctx.erasedTypes) { - assert(!TypeErasure.isUnboundedGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray + assert(!TypeErasure.isGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos) } else // after erasure newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos) diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 78568769305a..d3dceb4451cf 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -216,6 +216,16 @@ object TypeErasure { case _ => false } + /** Is `tp` an abstract type or polymorphic type parameter, or another unbounded generic type? */ + def isGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match { + case tp: TypeRef => !tp.symbol.isClass + case tp: TypeParamRef => true + case tp: TypeProxy => isGeneric(tp.underlying) + case tp: AndType => isGeneric(tp.tp1) || isGeneric(tp.tp2) + case tp: OrType => isGeneric(tp.tp1) || isGeneric(tp.tp2) + case _ => false + } + /** The erased least upper bound 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/transform/ArrayConstructors.scala b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala index c7d02d53175b..888696846ae7 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala @@ -46,10 +46,10 @@ class ArrayConstructors extends MiniPhase { val cs = tp.tpe.widen.classSymbol tree.fun match { case Apply(TypeApply(t: Ident, targ), dims) - if !TypeErasure.isUnboundedGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) => + if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) => rewrite(targ.head.tpe, dims) case Apply(TypeApply(t: Select, targ), dims) - if !TypeErasure.isUnboundedGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) => + if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) => Block(t.qualifier :: Nil, rewrite(targ.head.tpe, dims)) case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 313c91e1d953..9831c26c0596 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -831,7 +831,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => .select(defn.newGenericArrayMethod).withPos(tree.pos) .appliedToTypeTrees(targs).appliedToArgs(args) - if (TypeErasure.isUnboundedGeneric(targ.tpe)) + if (TypeErasure.isGeneric(targ.tpe)) newGenericArrayCall else tree case _ => diff --git a/tests/run/i4037.scala b/tests/run/i4037.scala new file mode 100644 index 000000000000..5679fb782445 --- /dev/null +++ b/tests/run/i4037.scala @@ -0,0 +1,8 @@ +import scala.reflect.ClassTag + +object Test { + def foo[T <: AnyRef : ClassTag] = new Array[T](42) + def main(args: Array[String]): Unit = { + val x: Array[String] = foo[String] + } +} \ No newline at end of file