@@ -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 =>
@@ -389,6 +392,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
389
392
else eraseNormalClassRef(tp)
390
393
case tp : AppliedType =>
391
394
if (tp.tycon.isRef(defn.ArrayClass )) eraseArray(tp)
395
+ else if (tp.tycon.isRef(defn.PairClass )) erasePair(tp)
392
396
else if (tp.isRepeatedParam) apply(tp.underlyingIfRepeated(isJava))
393
397
else apply(tp.superType)
394
398
case _ : TermRef | _ : ThisType =>
@@ -419,9 +423,13 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
419
423
case tp @ ClassInfo (pre, cls, parents, decls, _) =>
420
424
if (cls is Package ) tp
421
425
else {
426
+ def eraseParent (tp : Type ) = tp.dealias match {
427
+ case tp : AppliedType if tp.tycon.isRef(defn.PairClass ) => defn.ObjectType
428
+ case _ => apply(tp)
429
+ }
422
430
val erasedParents : List [Type ] =
423
431
if ((cls eq defn.ObjectClass ) || cls.isPrimitiveValueClass) Nil
424
- else parents.mapConserve(apply ) match {
432
+ else parents.mapConserve(eraseParent ) match {
425
433
case tr :: trs1 =>
426
434
assert(! tr.classSymbol.is(Trait ), cls)
427
435
val tr1 = if (cls is Trait ) defn.ObjectType else tr
@@ -449,6 +457,22 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
449
457
else JavaArrayType (arrayErasure(elemtp))
450
458
}
451
459
460
+ private def erasePair (tp : Type )(implicit ctx : Context ): Type = {
461
+ def tupleArity (tp : Type ): Int = tp.dealias match {
462
+ case AppliedType (tycon, _ :: tl :: Nil ) if tycon.isRef(defn.PairClass ) =>
463
+ val arity = tupleArity(tl)
464
+ if (arity < 0 ) arity else arity + 1
465
+ case tp1 =>
466
+ if (tp1.isRef(defn.UnitClass )) 0
467
+ else if (defn.isTupleClass(tp1.classSymbol)) tp1.dealias.argInfos.length
468
+ else - 1
469
+ }
470
+ val arity = tupleArity(tp)
471
+ if (arity < 0 ) defn.ObjectType
472
+ else if (arity <= Definitions .MaxTupleArity ) defn.TupleType (arity)
473
+ else defn.TupleXXLType
474
+ }
475
+
452
476
/** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s and
453
477
* `PolyType`s are treated. `eraseInfo` maps them them to method types, whereas `apply` maps them
454
478
* to the underlying type.
@@ -491,7 +515,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
491
515
// constructor method should not be semi-erased.
492
516
else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp)
493
517
else this (tp)
494
- case AppliedType (tycon, _) if ! (tycon isRef defn. ArrayClass ) =>
518
+ case AppliedType (tycon, _) if ! erasureDependsOnArgs (tycon) =>
495
519
eraseResult(tycon)
496
520
case _ =>
497
521
this (tp)
@@ -533,7 +557,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
533
557
normalizeClass(sym.asClass).fullName.asTypeName
534
558
case tp : AppliedType =>
535
559
sigName(
536
- if (tp.tycon.isRef(defn. ArrayClass )) this (tp)
560
+ if (erasureDependsOnArgs( tp.tycon)) this (tp)
537
561
else if (tp.tycon.typeSymbol.isClass) tp.underlying
538
562
else tp.superType)
539
563
case ErasedValueType (_, underlying) =>
0 commit comments