@@ -631,129 +631,131 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
631
631
* - For NoType or NoPrefix, the type itself.
632
632
* - For any other type, exception.
633
633
*/
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)
727
719
}
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
736
728
}
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
757
759
758
760
/** Like translucentSuperType, but issue a fatal error if it does not exist. */
759
761
private def checkedSuperType (tp : TypeProxy )(using Context ): Type =
0 commit comments