@@ -33,6 +33,9 @@ import scala.annotation.tailrec
3333 */
3434object TypeErasure {
3535
36+ private def erasureDependsOnArgs (tp : Type )(implicit ctx : Context ) =
37+ tp.isRef(defn.ArrayClass ) || tp.isRef(defn.PairClass )
38+
3639 /** A predicate that tests whether a type is a legal erased type. Only asInstanceOf and
3740 * isInstanceOf may have types that do not satisfy the predicate.
3841 * ErasedValueType is considered an erased type because it is valid after Erasure (it is
@@ -44,7 +47,7 @@ object TypeErasure {
4447 case tp : TypeRef =>
4548 val sym = tp.symbol
4649 sym.isClass &&
47- sym != defn. ArrayClass &&
50+ ! erasureDependsOnArgs(tp) &&
4851 ! defn.erasedToObject.contains(sym) &&
4952 ! defn.isSyntheticFunctionClass(sym)
5053 case _ : TermRef =>
@@ -388,6 +391,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
388391 else eraseNormalClassRef(tp)
389392 case tp : AppliedType =>
390393 if (tp.tycon.isRef(defn.ArrayClass )) eraseArray(tp)
394+ else if (tp.tycon.isRef(defn.PairClass )) erasePair(tp)
391395 else if (tp.isRepeatedParam) apply(tp.underlyingIfRepeated(isJava))
392396 else apply(tp.superType)
393397 case _ : TermRef | _ : ThisType =>
@@ -418,9 +422,13 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
418422 case tp @ ClassInfo (pre, cls, parents, decls, _) =>
419423 if (cls is Package ) tp
420424 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+ }
421429 val erasedParents : List [Type ] =
422430 if ((cls eq defn.ObjectClass ) || cls.isPrimitiveValueClass) Nil
423- else parents.mapConserve(apply ) match {
431+ else parents.mapConserve(eraseParent ) match {
424432 case tr :: trs1 =>
425433 assert(! tr.classSymbol.is(Trait ), cls)
426434 val tr1 = if (cls is Trait ) defn.ObjectType else tr
@@ -448,6 +456,22 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
448456 else JavaArrayType (arrayErasure(elemtp))
449457 }
450458
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+
451475 /** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s and
452476 * `PolyType`s are treated. `eraseInfo` maps them them to method types, whereas `apply` maps them
453477 * to the underlying type.
@@ -490,7 +514,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
490514 // constructor method should not be semi-erased.
491515 else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp)
492516 else this (tp)
493- case AppliedType (tycon, _) if ! (tycon isRef defn. ArrayClass ) =>
517+ case AppliedType (tycon, _) if ! erasureDependsOnArgs (tycon) =>
494518 eraseResult(tycon)
495519 case _ =>
496520 this (tp)
@@ -532,7 +556,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
532556 normalizeClass(sym.asClass).fullName.asTypeName
533557 case tp : AppliedType =>
534558 sigName(
535- if (tp.tycon.isRef(defn. ArrayClass )) this (tp)
559+ if (erasureDependsOnArgs( tp.tycon)) this (tp)
536560 else if (tp.tycon.typeSymbol.isClass) tp.underlying
537561 else tp.superType)
538562 case ErasedValueType (_, underlying) =>
0 commit comments