Skip to content

Commit aea5f3c

Browse files
authored
Merge pull request #8361 from dotty-staging/fix-array-sig
Fix #8349: Generic signatures of generic arrays
2 parents 3d3d147 + 4fe4a87 commit aea5f3c

File tree

4 files changed

+27
-72
lines changed

4 files changed

+27
-72
lines changed

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

Lines changed: 10 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import core.Flags._
99
import core.Names.{DerivedName, Name, SimpleName, TypeName}
1010
import core.Symbols._
1111
import core.TypeApplications.TypeParamInfo
12-
import core.TypeErasure.erasure
12+
import core.TypeErasure.{erasure, isUnboundedGeneric}
1313
import core.Types._
1414
import core.classfile.ClassfileConstants
1515
import ast.Trees._
@@ -182,15 +182,16 @@ object GenericSignatures {
182182
case ref @ TypeParamRef(_: PolyType, _) =>
183183
typeParamSig(ref.paramName.lastPart)
184184

185+
case defn.ArrayOf(elemtp) =>
186+
if (isUnboundedGeneric(elemtp))
187+
jsig(defn.ObjectType)
188+
else {
189+
builder.append(ClassfileConstants.ARRAY_TAG)
190+
jsig(elemtp)
191+
}
192+
185193
case RefOrAppliedType(sym, pre, args) =>
186-
// If args isEmpty, Array is being used as a type constructor
187-
if (sym == defn.ArrayClass && args.nonEmpty)
188-
if (unboundedGenericArrayLevel(tp) == 1) jsig(defn.ObjectType)
189-
else {
190-
builder.append(ClassfileConstants.ARRAY_TAG)
191-
args.foreach(jsig(_))
192-
}
193-
else if (sym == defn.PairClass && tp.tupleArity > Definitions.MaxTupleArity)
194+
if (sym == defn.PairClass && tp.tupleArity > Definitions.MaxTupleArity)
194195
jsig(defn.TupleXXLClass.typeRef)
195196
else if (isTypeParameterInSig(sym, sym0)) {
196197
assert(!sym.isAliasType, "Unexpected alias type: " + sym)
@@ -368,17 +369,6 @@ object GenericSignatures {
368369
case tp => tp :: Nil
369370
}
370371

371-
/** Arrays despite their finality may turn up as refined type parents,
372-
* e.g. with "tagged types" like Array[Int] with T.
373-
*/
374-
private def unboundedGenericArrayLevel(tp: Type)(implicit ctx: Context): Int = tp match {
375-
case GenericArray(core, level) if !(core <:< defn.AnyRefType) =>
376-
level
377-
case AndType(tp1, tp2) =>
378-
unboundedGenericArrayLevel(tp1) max unboundedGenericArrayLevel(tp2)
379-
case _ =>
380-
0
381-
}
382372

383373
// only refer to type params that will actually make it into the sig, this excludes:
384374
// * higher-order type parameters
@@ -420,53 +410,6 @@ object GenericSignatures {
420410
if (owner.is(PackageClass) || owner.isTerm) pre else cls.owner.info /* .tpe_* */
421411
}
422412

423-
object GenericArray {
424-
425-
/** Is `tp` an unbounded generic type (i.e. which could be instantiated
426-
* with primitive as well as class types)?.
427-
*/
428-
private def genericCore(tp: Type)(implicit ctx: Context): Type = tp.widenDealias match {
429-
/* A Java Array<T> is erased to Array[Object] (T can only be a reference type), where as a Scala Array[T] is
430-
* erased to Object. However, there is only symbol for the Array class. So to make the distinction between
431-
* a Java and a Scala array, we check if the owner of T comes from a Java class.
432-
* This however caused issue scala/bug#5654. The additional test for EXISTENTIAL fixes it, see the ticket comments.
433-
* In short, members of an existential type (e.g. `T` in `forSome { type T }`) can have pretty arbitrary
434-
* owners (e.g. when computing lubs, <root> is used). All packageClass symbols have `isJavaDefined == true`.
435-
*/
436-
case RefOrAppliedType(sym, tp, _) =>
437-
if (sym.isAbstractOrParamType && (!sym.owner.is(JavaDefined) || sym.is(Scala2Existential)))
438-
tp
439-
else
440-
NoType
441-
442-
case bounds: TypeBounds =>
443-
bounds
444-
445-
case _ =>
446-
NoType
447-
}
448-
449-
/** If `tp` is of the form Array[...Array[T]...] where `T` is an abstract type
450-
* then Some((N, T)) where N is the number of Array constructors enclosing `T`,
451-
* otherwise None. Existentials on any level are ignored.
452-
*/
453-
def unapply(tp: Type)(implicit ctx: Context): Option[(Type, Int)] = tp.widenDealias match {
454-
case defn.ArrayOf(arg) =>
455-
genericCore(arg) match {
456-
case NoType =>
457-
arg match {
458-
case GenericArray(core, level) => Some((core, level + 1))
459-
case _ => None
460-
}
461-
case core =>
462-
Some((core, 1))
463-
}
464-
case _ =>
465-
None
466-
}
467-
}
468-
469-
470413
private object RefOrAppliedType {
471414
def unapply(tp: Type)(implicit ctx: Context): Option[(Symbol, Type, List[Type])] = tp match {
472415
case TypeParamRef(_, _) =>

tests/generic-java-signatures/arrayBound.check

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ T <: java.lang.Object
22
U <: T[]
33
V <: java.util.List<T[]>
44
W <: java.util.List<? extends java.util.Date>
5-
X <: java.util.HashMap<java.lang.Object, java.util.ArrayList<? extends java.util.Date>>
5+
X <: java.util.HashMap<java.lang.Object, java.util.ArrayList<? extends java.util.Date>>
6+
T1 <: java.lang.Object
7+
U1 <: java.lang.Object
8+
V1 <: java.lang.Object[]
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
class Foo[T <: Array[_], U <: Array[T], V <: java.util.List[Array[T]], W <: java.util.List[_ <: java.util.Date], X <: java.util.HashMap[Array[_], java.util.ArrayList[_ <: java.util.Date]]]
1+
class Foo[
2+
T <: Array[_],
3+
U <: Array[T],
4+
V <: java.util.List[Array[T]],
5+
W <: java.util.List[_ <: java.util.Date],
6+
X <: java.util.HashMap[Array[_], java.util.ArrayList[_ <: java.util.Date]],
7+
T1,
8+
U1 <: Array[T1],
9+
V1 <: Array[Array[T1]]
10+
]
211
object Test {
312
def main(args: Array[String]): Unit = {
4-
val tParams = classOf[Foo[_, _, _, _, _]].getTypeParameters()
13+
val tParams = classOf[Foo[_, _, _, _, _, _, _, _]].getTypeParameters()
514
tParams.foreach { tp =>
615
println(tp.getName + " <: " + tp.getBounds.map(_.getTypeName).mkString(", "))
716
}
817
}
9-
}
18+
}

tests/generic-java-signatures/primitives.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ E <: int[]
66
F <: long[]
77
G <: short[]
88
H <: boolean[]
9-
I <: java.lang.Object
9+
I <: byte[]

0 commit comments

Comments
 (0)