From d26604fd50bd2c444c9dd108781d36864380b5f2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 6 May 2015 10:22:19 +0200 Subject: [PATCH 1/3] Fix #540 - unbounded array test for wildcard array arguments Arrays with wildcard arguments such as Array[_ <: Foo] where Foo is a universal trait are now diagnosed as unbounded generic arrays and are erased to Object. --- src/dotty/tools/dotc/core/TypeErasure.scala | 4 +++- tests/pos/i540.scala | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i540.scala diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 71146bd4e19d..f499e2ece9fa 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -182,13 +182,14 @@ object TypeErasure { case tp: PolyParam => !tp.derivesFrom(defn.ObjectClass) && !tp.binder.resultType.isInstanceOf[JavaMethodType] + case tp: TypeAlias => isUnboundedGeneric(tp.alias) + case tp: TypeBounds => !tp.hi.derivesFrom(defn.ObjectClass) case tp: TypeProxy => isUnboundedGeneric(tp.underlying) case tp: AndType => isUnboundedGeneric(tp.tp1) || isUnboundedGeneric(tp.tp2) case tp: OrType => isUnboundedGeneric(tp.tp1) && isUnboundedGeneric(tp.tp2) case _ => false } - /** The erased least upper bound is computed as follows * - if both argument are arrays, an array of the lub of the element types * - if one argument is an array, Object @@ -365,6 +366,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean val defn.ArrayType(elemtp) = tp def arrayErasure(tpToErase: Type) = erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) + println(s"erase array, elemtp = $elemtp") if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType) else if (isUnboundedGeneric(elemtp)) defn.ObjectType else JavaArrayType(arrayErasure(elemtp)) diff --git a/tests/pos/i540.scala b/tests/pos/i540.scala new file mode 100644 index 000000000000..b7540ab2cab4 --- /dev/null +++ b/tests/pos/i540.scala @@ -0,0 +1,6 @@ +trait Foo extends Any + +object Univ { + def univ[T <: Foo](x: Array[T]) = {} + def univ2(x: Array[_ <: Foo]) = {} +} From 650ef40888b585d10e0a87a4a9544c1c6e17c96f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 6 May 2015 10:29:19 +0200 Subject: [PATCH 2/3] Remove debug println --- src/dotty/tools/dotc/core/TypeErasure.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index f499e2ece9fa..183b847e66f5 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -366,7 +366,6 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean val defn.ArrayType(elemtp) = tp def arrayErasure(tpToErase: Type) = erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) - println(s"erase array, elemtp = $elemtp") if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType) else if (isUnboundedGeneric(elemtp)) defn.ObjectType else JavaArrayType(arrayErasure(elemtp)) From df0e140645ec558db8385a0d2322f159aa9bbda4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 8 May 2015 11:11:11 +0200 Subject: [PATCH 3/3] Fixed foc of isUnboudnedGenericArray --- src/dotty/tools/dotc/core/TypeErasure.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 183b847e66f5..65bc5e57fd6e 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -170,9 +170,9 @@ object TypeErasure { } } - /** Is `tp` an abstract type or polymorphic type parameter that has `Any` - * as upper bound and that is not Java defined? Arrays of such types are - * erased to `Object` instead of `ObjectArray`. + /** Is `tp` an abstract type or polymorphic type parameter that has `Any`, `AnyVal`, + * or a universal trait as upper bound and that is not Java defined? Arrays of such types are + * erased to `Object` instead of `Object[]`. */ def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match { case tp: TypeRef =>