@@ -631,129 +631,131 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
631631 * - For NoType or NoPrefix, the type itself.
632632 * - For any other type, exception.
633633 */
634- private def apply (tp : Type )(using Context ): Type | Null = (tp match
635- case _ : ErasedValueType =>
636- tp
637- case tp : TypeRef =>
638- val sym = tp.symbol
639- if ! sym.isClass then this (checkedSuperType(tp))
640- else if semiEraseVCs && isDerivedValueClass(sym) then eraseDerivedValueClass(tp)
641- else if defn.isSyntheticFunctionClass(sym) then defn.functionTypeErasure(sym)
642- else eraseNormalClassRef(tp)
643- case tp : AppliedType =>
644- val tycon = tp.tycon
645- if (tycon.isRef(defn.ArrayClass )) eraseArray(tp)
646- else if (tycon.isRef(defn.PairClass )) erasePair(tp)
647- else if (tp.isRepeatedParam) apply(tp.translateFromRepeated(toArray = sourceLanguage.isJava))
648- else if (semiEraseVCs && isDerivedValueClass(tycon.classSymbol)) eraseDerivedValueClass(tp)
649- else this (checkedSuperType(tp))
650- case tp : TermRef =>
651- this (underlyingOfTermRef(tp))
652- case _ : ThisType =>
653- this (tp.widen)
654- case SuperType (thistpe, supertpe) =>
655- val eThis = this (thistpe)
656- val eSuper = this (supertpe)
657- if eThis == null || eSuper == null then null
658- else SuperType (eThis, eSuper)
659- case ExprType (rt) =>
660- defn.FunctionType (0 )
661- case RefinedType (parent, nme.apply, refinedInfo) if parent.typeSymbol eq defn.PolyFunctionClass =>
662- erasePolyFunctionApply(refinedInfo)
663- case RefinedType (parent, nme.apply, refinedInfo : MethodType ) if defn.isErasedFunctionType(parent) =>
664- eraseErasedFunctionApply(refinedInfo)
665- case tp : TypeVar if ! tp.isInstantiated =>
666- assert(inSigName, i " Cannot erase uninstantiated type variable $tp" )
667- null
668- case tp : TypeProxy =>
669- this (tp.underlying)
670- case tp @ AndType (tp1, tp2) =>
671- if sourceLanguage.isJava then
672- this (tp1)
673- else if sourceLanguage.isScala2 then
674- this (Scala2Erasure .intersectionDominator(Scala2Erasure .flattenedParents(tp)))
675- else
676- val e1 = this (tp1)
677- val e2 = this (tp2)
678- if e1 == null || e2 == null then null
679- else erasedGlb(e1, e2)
680- case OrType (tp1, tp2) =>
681- if isSymbol && sourceLanguage.isScala2 && ctx.settings.scalajs.value then
682- // In Scala2Unpickler we unpickle Scala.js pseudo-unions as if they were
683- // real unions, but we must still erase them as Scala 2 would to emit
684- // the correct signatures in SJSIR.
685- // We only do this when `isSymbol` is true since in other situations we
686- // cannot distinguish a Scala.js pseudo-union from a Scala 3 union that
687- // has been substituted into a Scala 2 type (e.g., via `asSeenFrom`),
688- // erasing these unions as if they were pseudo-unions could have an
689- // impact on overriding relationships so it's best to leave them
690- // alone (and this doesn't impact the SJSIR we generate).
691- JSDefinitions .jsdefn.PseudoUnionType
692- else
693- val e1 = this (tp1)
694- val e2 = this (tp2)
695- if e1 == null || e2 == null then null
696- else TypeComparer .orType(e1, e2, isErased = true )
697- case tp : MethodType =>
698- def paramErasure (tpToErase : Type ) =
699- erasureFn(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, inSigName = false )(tpToErase).nn
700- val (names, formals0) = if tp.hasErasedParams then
701- tp.paramNames
702- .zip(tp.paramInfos)
703- .zip(tp.erasedParams)
704- .collect{ case (param, isErased) if ! isErased => param }
705- .unzip
706- else (tp.paramNames, tp.paramInfos)
707- val formals = formals0.mapConserve(paramErasure)
708- eraseResult(tp.resultType) match {
709- case rt : MethodType =>
710- tp.derivedLambdaType(names ++ rt.paramNames, formals ++ rt.paramInfos, rt.resultType)
711- case NoType =>
712- // Can happen if we smuggle in a Nothing in the qualifier. Normally we prevent that
713- // in Checking.checkMembersOK, but compiler-generated code can bypass this test.
714- // See i15377.scala for a test case.
715- NoType
716- case rt =>
717- tp.derivedLambdaType(names, formals, rt)
718- }
719- case tp : PolyType =>
720- this (tp.resultType)
721- case tp @ ClassInfo (pre, cls, parents, decls, _) =>
722- if (cls.is(Package )) tp
723- else {
724- def eraseParent (tp : Type ) = tp.dealias match { // note: can't be opaque, since it's a class parent
725- case tp : AppliedType if tp.tycon.isRef(defn.PairClass ) => defn.ObjectType
726- case _ => apply(tp).nn
634+ private def apply (tp : Type )(using Context ): Type | Null =
635+ val etp = tp match
636+ case _ : ErasedValueType =>
637+ tp
638+ case tp : TypeRef =>
639+ val sym = tp.symbol
640+ if ! sym.isClass then this (checkedSuperType(tp))
641+ else if semiEraseVCs && isDerivedValueClass(sym) then eraseDerivedValueClass(tp)
642+ else if defn.isSyntheticFunctionClass(sym) then defn.functionTypeErasure(sym)
643+ else eraseNormalClassRef(tp)
644+ case tp : AppliedType =>
645+ val tycon = tp.tycon
646+ if (tycon.isRef(defn.ArrayClass )) eraseArray(tp)
647+ else if (tycon.isRef(defn.PairClass )) erasePair(tp)
648+ else if (tp.isRepeatedParam) apply(tp.translateFromRepeated(toArray = sourceLanguage.isJava))
649+ else if (semiEraseVCs && isDerivedValueClass(tycon.classSymbol)) eraseDerivedValueClass(tp)
650+ else this (checkedSuperType(tp))
651+ case tp : TermRef =>
652+ this (underlyingOfTermRef(tp))
653+ case _ : ThisType =>
654+ this (tp.widen)
655+ case SuperType (thistpe, supertpe) =>
656+ val eThis = this (thistpe)
657+ val eSuper = this (supertpe)
658+ if eThis == null || eSuper == null then null
659+ else SuperType (eThis, eSuper)
660+ case ExprType (rt) =>
661+ defn.FunctionType (0 )
662+ case RefinedType (parent, nme.apply, refinedInfo) if parent.typeSymbol eq defn.PolyFunctionClass =>
663+ erasePolyFunctionApply(refinedInfo)
664+ case RefinedType (parent, nme.apply, refinedInfo : MethodType ) if defn.isErasedFunctionType(parent) =>
665+ eraseErasedFunctionApply(refinedInfo)
666+ case tp : TypeVar if ! tp.isInstantiated =>
667+ assert(inSigName, i " Cannot erase uninstantiated type variable $tp" )
668+ null
669+ case tp : TypeProxy =>
670+ this (tp.underlying)
671+ case tp @ AndType (tp1, tp2) =>
672+ if sourceLanguage.isJava then
673+ this (tp1)
674+ else if sourceLanguage.isScala2 then
675+ this (Scala2Erasure .intersectionDominator(Scala2Erasure .flattenedParents(tp)))
676+ else
677+ val e1 = this (tp1)
678+ val e2 = this (tp2)
679+ if e1 == null || e2 == null then null
680+ else erasedGlb(e1, e2)
681+ case OrType (tp1, tp2) =>
682+ if isSymbol && sourceLanguage.isScala2 && ctx.settings.scalajs.value then
683+ // In Scala2Unpickler we unpickle Scala.js pseudo-unions as if they were
684+ // real unions, but we must still erase them as Scala 2 would to emit
685+ // the correct signatures in SJSIR.
686+ // We only do this when `isSymbol` is true since in other situations we
687+ // cannot distinguish a Scala.js pseudo-union from a Scala 3 union that
688+ // has been substituted into a Scala 2 type (e.g., via `asSeenFrom`),
689+ // erasing these unions as if they were pseudo-unions could have an
690+ // impact on overriding relationships so it's best to leave them
691+ // alone (and this doesn't impact the SJSIR we generate).
692+ JSDefinitions .jsdefn.PseudoUnionType
693+ else
694+ val e1 = this (tp1)
695+ val e2 = this (tp2)
696+ if e1 == null || e2 == null then null
697+ else TypeComparer .orType(e1, e2, isErased = true )
698+ case tp : MethodType =>
699+ def paramErasure (tpToErase : Type ) =
700+ erasureFn(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, inSigName = false )(tpToErase).nn
701+ val (names, formals0) = if tp.hasErasedParams then
702+ tp.paramNames
703+ .zip(tp.paramInfos)
704+ .zip(tp.erasedParams)
705+ .collect{ case (param, isErased) if ! isErased => param }
706+ .unzip
707+ else (tp.paramNames, tp.paramInfos)
708+ val formals = formals0.mapConserve(paramErasure)
709+ eraseResult(tp.resultType) match {
710+ case rt : MethodType =>
711+ tp.derivedLambdaType(names ++ rt.paramNames, formals ++ rt.paramInfos, rt.resultType)
712+ case NoType =>
713+ // Can happen if we smuggle in a Nothing in the qualifier. Normally we prevent that
714+ // in Checking.checkMembersOK, but compiler-generated code can bypass this test.
715+ // See i15377.scala for a test case.
716+ NoType
717+ case rt =>
718+ tp.derivedLambdaType(names, formals, rt)
727719 }
728- val erasedParents : List [ Type ] =
729- if ((cls eq defn. ObjectClass ) || cls.isPrimitiveValueClass) Nil
730- else parents.mapConserve(eraseParent) match {
731- case tr :: trs1 =>
732- assert( ! tr.classSymbol.is( Trait ), i " $cls has bad parents $parents %, % " )
733- val tr1 = if (cls.is( Trait )) defn. ObjectType else tr
734- tr1 :: trs1.filterNot(_.isAnyRef)
735- case nil => nil
720+ case tp : PolyType =>
721+ this (tp.resultType)
722+ case tp @ ClassInfo (pre, cls, parents, decls, _) =>
723+ if (cls.is( Package )) tp
724+ else {
725+ def eraseParent ( tp : Type ) = tp.dealias match { // note: can't be opaque, since it's a class parent
726+ case tp : AppliedType if tp.tycon.isRef(defn. PairClass ) => defn. ObjectType
727+ case _ => apply(tp).nn
736728 }
737- var erasedDecls = decls.filteredScope(sym => ! sym.isType || sym.isClass).openForMutations
738- for dcl <- erasedDecls.iterator do
739- if dcl.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot ).isDefined
740- && dcl.targetName != dcl.name
741- then
742- if erasedDecls eq decls then erasedDecls = erasedDecls.cloneScope
743- erasedDecls.unlink(dcl)
744- erasedDecls.enter(dcl.targetName, dcl)
745- val selfType1 = if cls.is(Module ) then cls.sourceModule.termRef else NoType
746- tp.derivedClassInfo(NoPrefix , erasedParents, erasedDecls, selfType1)
747- // can't replace selftype by NoType because this would lose the sourceModule link
748- }
749- case _ : ErrorType | JavaArrayType (_) =>
750- tp
751- case tp : WildcardType =>
752- assert(inSigName, i " Cannot erase wildcard type $tp" )
753- null
754- case tp if (tp `eq` NoType ) || (tp `eq` NoPrefix ) =>
755- tp
756- ).ensuring(etp => etp != null || inSigName)
729+ val erasedParents : List [Type ] =
730+ if ((cls eq defn.ObjectClass ) || cls.isPrimitiveValueClass) Nil
731+ else parents.mapConserve(eraseParent) match {
732+ case tr :: trs1 =>
733+ assert(! tr.classSymbol.is(Trait ), i " $cls has bad parents $parents%, % " )
734+ val tr1 = if (cls.is(Trait )) defn.ObjectType else tr
735+ tr1 :: trs1.filterNot(_.isAnyRef)
736+ case nil => nil
737+ }
738+ var erasedDecls = decls.filteredScope(sym => ! sym.isType || sym.isClass).openForMutations
739+ for dcl <- erasedDecls.iterator do
740+ if dcl.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot ).isDefined
741+ && dcl.targetName != dcl.name
742+ then
743+ if erasedDecls eq decls then erasedDecls = erasedDecls.cloneScope
744+ erasedDecls.unlink(dcl)
745+ erasedDecls.enter(dcl.targetName, dcl)
746+ val selfType1 = if cls.is(Module ) then cls.sourceModule.termRef else NoType
747+ tp.derivedClassInfo(NoPrefix , erasedParents, erasedDecls, selfType1)
748+ // can't replace selftype by NoType because this would lose the sourceModule link
749+ }
750+ case _ : ErrorType | JavaArrayType (_) =>
751+ tp
752+ case tp : WildcardType =>
753+ assert(inSigName, i " Cannot erase wildcard type $tp" )
754+ null
755+ case tp if (tp `eq` NoType ) || (tp `eq` NoPrefix ) =>
756+ tp
757+ assert(etp != null || inSigName, i " Unexpected null erasure for $tp" )
758+ etp
757759
758760 /** Like translucentSuperType, but issue a fatal error if it does not exist. */
759761 private def checkedSuperType (tp : TypeProxy )(using Context ): Type =
0 commit comments