@@ -33,6 +33,9 @@ import scala.annotation.tailrec
33
33
*/
34
34
object TypeErasure {
35
35
36
+ private def erasureDependsOnArgs (tp : Type )(implicit ctx : Context ) =
37
+ tp.isRef(defn.ArrayClass ) || tp.isRef(defn.PairClass )
38
+
36
39
/** A predicate that tests whether a type is a legal erased type. Only asInstanceOf and
37
40
* isInstanceOf may have types that do not satisfy the predicate.
38
41
* ErasedValueType is considered an erased type because it is valid after Erasure (it is
@@ -44,7 +47,7 @@ object TypeErasure {
44
47
case tp : TypeRef =>
45
48
val sym = tp.symbol
46
49
sym.isClass &&
47
- sym != defn. ArrayClass &&
50
+ ! erasureDependsOnArgs(tp) &&
48
51
! defn.erasedToObject.contains(sym) &&
49
52
! defn.isSyntheticFunctionClass(sym)
50
53
case _ : TermRef =>
@@ -388,6 +391,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
388
391
else eraseNormalClassRef(tp)
389
392
case tp : AppliedType =>
390
393
if (tp.tycon.isRef(defn.ArrayClass )) eraseArray(tp)
394
+ else if (tp.tycon.isRef(defn.PairClass )) erasePair(tp)
391
395
else if (tp.isRepeatedParam) apply(tp.underlyingIfRepeated(isJava))
392
396
else apply(tp.superType)
393
397
case _ : TermRef | _ : ThisType =>
@@ -418,9 +422,13 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
418
422
case tp @ ClassInfo (pre, cls, parents, decls, _) =>
419
423
if (cls is Package ) tp
420
424
else {
425
+ def eraseParent (tp : Type ) = tp.dealias match {
426
+ case tp : AppliedType if tp.tycon.isRef(defn.PairClass ) => defn.ObjectType
427
+ case _ => apply(tp)
428
+ }
421
429
val erasedParents : List [Type ] =
422
430
if ((cls eq defn.ObjectClass ) || cls.isPrimitiveValueClass) Nil
423
- else parents.mapConserve(apply ) match {
431
+ else parents.mapConserve(eraseParent ) match {
424
432
case tr :: trs1 =>
425
433
assert(! tr.classSymbol.is(Trait ), cls)
426
434
val tr1 = if (cls is Trait ) defn.ObjectType else tr
@@ -448,6 +456,22 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
448
456
else JavaArrayType (arrayErasure(elemtp))
449
457
}
450
458
459
+ private def erasePair (tp : Type )(implicit ctx : Context ): Type = {
460
+ def tupleArity (tp : Type ): Int = tp.dealias match {
461
+ case AppliedType (tycon, _ :: tl :: Nil ) if tycon.isRef(defn.PairClass ) =>
462
+ val arity = tupleArity(tl)
463
+ if (arity < 0 ) arity else arity + 1
464
+ case tp1 =>
465
+ if (tp1.isRef(defn.UnitClass )) 0
466
+ else if (defn.isTupleClass(tp1.classSymbol)) tp1.dealias.argInfos.length
467
+ else - 1
468
+ }
469
+ val arity = tupleArity(tp)
470
+ if (arity < 0 ) defn.ObjectType
471
+ else if (arity <= Definitions .MaxTupleArity ) defn.TupleType (arity)
472
+ else defn.TupleXXLType
473
+ }
474
+
451
475
/** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s and
452
476
* `PolyType`s are treated. `eraseInfo` maps them them to method types, whereas `apply` maps them
453
477
* to the underlying type.
@@ -490,7 +514,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
490
514
// constructor method should not be semi-erased.
491
515
else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp)
492
516
else this (tp)
493
- case AppliedType (tycon, _) if ! (tycon isRef defn. ArrayClass ) =>
517
+ case AppliedType (tycon, _) if ! erasureDependsOnArgs (tycon) =>
494
518
eraseResult(tycon)
495
519
case _ =>
496
520
this (tp)
@@ -532,7 +556,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
532
556
normalizeClass(sym.asClass).fullName.asTypeName
533
557
case tp : AppliedType =>
534
558
sigName(
535
- if (tp.tycon.isRef(defn. ArrayClass )) this (tp)
559
+ if (erasureDependsOnArgs( tp.tycon)) this (tp)
536
560
else if (tp.tycon.typeSymbol.isClass) tp.underlying
537
561
else tp.superType)
538
562
case ErasedValueType (_, underlying) =>
0 commit comments