@@ -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 =>
@@ -389,6 +392,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
389392 else eraseNormalClassRef(tp)
390393 case tp : AppliedType =>
391394 if (tp.tycon.isRef(defn.ArrayClass )) eraseArray(tp)
395+ else if (tp.tycon.isRef(defn.PairClass )) erasePair(tp)
392396 else if (tp.isRepeatedParam) apply(tp.underlyingIfRepeated(isJava))
393397 else apply(tp.superType)
394398 case _ : TermRef | _ : ThisType =>
@@ -419,9 +423,13 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
419423 case tp @ ClassInfo (pre, cls, parents, decls, _) =>
420424 if (cls is Package ) tp
421425 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+ }
422430 val erasedParents : List [Type ] =
423431 if ((cls eq defn.ObjectClass ) || cls.isPrimitiveValueClass) Nil
424- else parents.mapConserve(apply ) match {
432+ else parents.mapConserve(eraseParent ) match {
425433 case tr :: trs1 =>
426434 assert(! tr.classSymbol.is(Trait ), cls)
427435 val tr1 = if (cls is Trait ) defn.ObjectType else tr
@@ -449,6 +457,22 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
449457 else JavaArrayType (arrayErasure(elemtp))
450458 }
451459
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+
452476 /** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s and
453477 * `PolyType`s are treated. `eraseInfo` maps them them to method types, whereas `apply` maps them
454478 * to the underlying type.
@@ -491,7 +515,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
491515 // constructor method should not be semi-erased.
492516 else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp)
493517 else this (tp)
494- case AppliedType (tycon, _) if ! (tycon isRef defn. ArrayClass ) =>
518+ case AppliedType (tycon, _) if ! erasureDependsOnArgs (tycon) =>
495519 eraseResult(tycon)
496520 case _ =>
497521 this (tp)
@@ -533,7 +557,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
533557 normalizeClass(sym.asClass).fullName.asTypeName
534558 case tp : AppliedType =>
535559 sigName(
536- if (tp.tycon.isRef(defn. ArrayClass )) this (tp)
560+ if (erasureDependsOnArgs( tp.tycon)) this (tp)
537561 else if (tp.tycon.typeSymbol.isClass) tp.underlying
538562 else tp.superType)
539563 case ErasedValueType (_, underlying) =>
0 commit comments