@@ -9,6 +9,7 @@ import Uniques.unique
99import dotc .transform .ExplicitOuter ._
1010import dotc .transform .ValueClasses ._
1111import util .DotClass
12+ import transform .TypeUtils ._
1213import Definitions .MaxImplementedFunctionArity
1314import scala .annotation .tailrec
1415
@@ -33,6 +34,9 @@ import scala.annotation.tailrec
3334 */
3435object TypeErasure {
3536
37+ private def erasureDependsOnArgs (tp : Type )(implicit ctx : Context ) =
38+ tp.isRef(defn.ArrayClass ) || tp.isRef(defn.PairClass )
39+
3640 /** A predicate that tests whether a type is a legal erased type. Only asInstanceOf and
3741 * isInstanceOf may have types that do not satisfy the predicate.
3842 * ErasedValueType is considered an erased type because it is valid after Erasure (it is
@@ -44,7 +48,8 @@ object TypeErasure {
4448 case tp : TypeRef =>
4549 val sym = tp.symbol
4650 sym.isClass &&
47- sym != defn.AnyClass && sym != defn.ArrayClass &&
51+ ! erasureDependsOnArgs(tp) &&
52+ ! defn.erasedToObject.contains(sym) &&
4853 ! defn.isSyntheticFunctionClass(sym)
4954 case _ : TermRef =>
5055 true
@@ -280,10 +285,8 @@ object TypeErasure {
280285
281286 // Pick the last minimum to prioritise classes over traits
282287 minimums.lastOption match {
283- case Some (lub) if lub != defn.AnyClass && lub != defn.AnyValClass =>
284- lub.typeRef
285- case _ => // Any/AnyVal only exist before erasure
286- defn.ObjectType
288+ case Some (lub) => valueErasure(lub.typeRef)
289+ case _ => defn.ObjectType
287290 }
288291 }
289292 }
@@ -354,7 +357,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
354357 * - otherwise, if T is a type parameter coming from Java, []Object
355358 * - otherwise, Object
356359 * - For a term ref p.x, the type <noprefix> # x.
357- * - For a typeref scala.Any, scala.AnyVal or scala.Singleton : |java.lang.Object|
360+ * - For a typeref scala.Any, scala.AnyVal, scala.Singleton, scala.Tuple, or scala.*: : |java.lang.Object|
358361 * - For a typeref scala.Unit, |scala.runtime.BoxedUnit|.
359362 * - For a typeref scala.FunctionN, where N > MaxImplementedFunctionArity, scala.FunctionXXL
360363 * - For a typeref scala.ImplicitFunctionN, | scala.FunctionN |
@@ -390,6 +393,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
390393 else eraseNormalClassRef(tp)
391394 case tp : AppliedType =>
392395 if (tp.tycon.isRef(defn.ArrayClass )) eraseArray(tp)
396+ else if (tp.tycon.isRef(defn.PairClass )) erasePair(tp)
393397 else if (tp.isRepeatedParam) apply(tp.underlyingIfRepeated(isJava))
394398 else apply(tp.superType)
395399 case _ : TermRef | _ : ThisType =>
@@ -420,9 +424,13 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
420424 case tp @ ClassInfo (pre, cls, parents, decls, _) =>
421425 if (cls is Package ) tp
422426 else {
427+ def eraseParent (tp : Type ) = tp.dealias match {
428+ case tp : AppliedType if tp.tycon.isRef(defn.PairClass ) => defn.ObjectType
429+ case _ => apply(tp)
430+ }
423431 val erasedParents : List [Type ] =
424432 if ((cls eq defn.ObjectClass ) || cls.isPrimitiveValueClass) Nil
425- else parents.mapConserve(apply ) match {
433+ else parents.mapConserve(eraseParent ) match {
426434 case tr :: trs1 =>
427435 assert(! tr.classSymbol.is(Trait ), cls)
428436 val tr1 = if (cls is Trait ) defn.ObjectType else tr
@@ -450,6 +458,13 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
450458 else JavaArrayType (arrayErasure(elemtp))
451459 }
452460
461+ private def erasePair (tp : Type )(implicit ctx : Context ): Type = {
462+ val arity = tp.tupleArity
463+ if (arity < 0 ) defn.ObjectType
464+ else if (arity <= Definitions .MaxTupleArity ) defn.TupleType (arity)
465+ else defn.TupleXXLType
466+ }
467+
453468 /** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s and
454469 * `PolyType`s are treated. `eraseInfo` maps them them to method types, whereas `apply` maps them
455470 * to the underlying type.
@@ -492,15 +507,15 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
492507 // constructor method should not be semi-erased.
493508 else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp)
494509 else this (tp)
495- case AppliedType (tycon, _) if ! (tycon isRef defn. ArrayClass ) =>
510+ case AppliedType (tycon, _) if ! erasureDependsOnArgs (tycon) =>
496511 eraseResult(tycon)
497512 case _ =>
498513 this (tp)
499514 }
500515
501516 private def normalizeClass (cls : ClassSymbol )(implicit ctx : Context ): ClassSymbol = {
502517 if (cls.owner == defn.ScalaPackageClass ) {
503- if (cls == defn.AnyClass || cls == defn. AnyValClass || cls == defn. SingletonClass )
518+ if (defn.erasedToObject.contains( cls) )
504519 return defn.ObjectClass
505520 if (cls == defn.UnitClass )
506521 return defn.BoxedUnitClass
@@ -534,7 +549,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
534549 normalizeClass(sym.asClass).fullName.asTypeName
535550 case tp : AppliedType =>
536551 sigName(
537- if (tp.tycon.isRef(defn. ArrayClass )) this (tp)
552+ if (erasureDependsOnArgs( tp.tycon)) this (tp)
538553 else if (tp.tycon.typeSymbol.isClass) tp.underlying
539554 else tp.superType)
540555 case ErasedValueType (_, underlying) =>
0 commit comments