@@ -142,29 +142,31 @@ object TypeErasure {
142142 }
143143 }
144144
145- private def erasureIdx (sourceLanguage : SourceLanguage , semiEraseVCs : Boolean , isConstructor : Boolean , wildcardOK : Boolean ) =
145+ private def erasureIdx (sourceLanguage : SourceLanguage , semiEraseVCs : Boolean , isConstructor : Boolean , isSymbol : Boolean , wildcardOK : Boolean ) =
146146 extension (b : Boolean ) def toInt = if b then 1 else 0
147147 wildcardOK.toInt
148- + (isConstructor.toInt << 1 )
149- + (semiEraseVCs.toInt << 2 )
150- + (sourceLanguage.ordinal << 3 )
148+ + (isSymbol.toInt << 1 )
149+ + (isConstructor.toInt << 2 )
150+ + (semiEraseVCs.toInt << 3 )
151+ + (sourceLanguage.ordinal << 4 )
151152
152- private val erasures = new Array [TypeErasure ](1 << (SourceLanguage .bits + 3 ))
153+ private val erasures = new Array [TypeErasure ](1 << (SourceLanguage .bits + 4 ))
153154
154155 for
155156 sourceLanguage <- SourceLanguage .values
156157 semiEraseVCs <- List (false , true )
157158 isConstructor <- List (false , true )
159+ isSymbol <- List (false , true )
158160 wildcardOK <- List (false , true )
159161 do
160- erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK)) =
161- new TypeErasure (sourceLanguage, semiEraseVCs, isConstructor, wildcardOK)
162+ erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK)) =
163+ new TypeErasure (sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK)
162164
163165 /** Produces an erasure function. See the documentation of the class [[TypeErasure ]]
164166 * for a description of each parameter.
165167 */
166- private def erasureFn (sourceLanguage : SourceLanguage , semiEraseVCs : Boolean , isConstructor : Boolean , wildcardOK : Boolean ): TypeErasure =
167- erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK))
168+ private def erasureFn (sourceLanguage : SourceLanguage , semiEraseVCs : Boolean , isConstructor : Boolean , isSymbol : Boolean , wildcardOK : Boolean ): TypeErasure =
169+ erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK))
168170
169171 /** The current context with a phase no later than erasure */
170172 def preErasureCtx (using Context ) =
@@ -175,19 +177,19 @@ object TypeErasure {
175177 * @param tp The type to erase.
176178 */
177179 def erasure (tp : Type )(using Context ): Type =
178- erasureFn(sourceLanguage = SourceLanguage .Scala3 , semiEraseVCs = false , isConstructor = false , wildcardOK = false )(tp)(using preErasureCtx)
180+ erasureFn(sourceLanguage = SourceLanguage .Scala3 , semiEraseVCs = false , isConstructor = false , isSymbol = false , wildcardOK = false )(tp)(using preErasureCtx)
179181
180182 /** The value class erasure of a Scala type, where value classes are semi-erased to
181183 * ErasedValueType (they will be fully erased in [[ElimErasedValueType ]]).
182184 *
183185 * @param tp The type to erase.
184186 */
185187 def valueErasure (tp : Type )(using Context ): Type =
186- erasureFn(sourceLanguage = SourceLanguage .Scala3 , semiEraseVCs = true , isConstructor = false , wildcardOK = false )(tp)(using preErasureCtx)
188+ erasureFn(sourceLanguage = SourceLanguage .Scala3 , semiEraseVCs = true , isConstructor = false , isSymbol = false , wildcardOK = false )(tp)(using preErasureCtx)
187189
188190 /** The erasure that Scala 2 would use for this type. */
189191 def scala2Erasure (tp : Type )(using Context ): Type =
190- erasureFn(sourceLanguage = SourceLanguage .Scala2 , semiEraseVCs = true , isConstructor = false , wildcardOK = false )(tp)(using preErasureCtx)
192+ erasureFn(sourceLanguage = SourceLanguage .Scala2 , semiEraseVCs = true , isConstructor = false , isSymbol = false , wildcardOK = false )(tp)(using preErasureCtx)
191193
192194 /** Like value class erasure, but value classes erase to their underlying type erasure */
193195 def fullErasure (tp : Type )(using Context ): Type =
@@ -197,7 +199,7 @@ object TypeErasure {
197199
198200 def sigName (tp : Type , sourceLanguage : SourceLanguage )(using Context ): TypeName = {
199201 val normTp = tp.translateFromRepeated(toArray = sourceLanguage.isJava)
200- val erase = erasureFn(sourceLanguage, semiEraseVCs = ! sourceLanguage.isJava, isConstructor = false , wildcardOK = true )
202+ val erase = erasureFn(sourceLanguage, semiEraseVCs = ! sourceLanguage.isJava, isConstructor = false , isSymbol = false , wildcardOK = true )
201203 erase.sigName(normTp)(using preErasureCtx)
202204 }
203205
@@ -227,7 +229,7 @@ object TypeErasure {
227229 def transformInfo (sym : Symbol , tp : Type )(using Context ): Type = {
228230 val sourceLanguage = SourceLanguage (sym)
229231 val semiEraseVCs = ! sourceLanguage.isJava // Java sees our value classes as regular classes.
230- val erase = erasureFn(sourceLanguage, semiEraseVCs, sym.isConstructor, wildcardOK = false )
232+ val erase = erasureFn(sourceLanguage, semiEraseVCs, sym.isConstructor, isSymbol = true , wildcardOK = false )
231233
232234 def eraseParamBounds (tp : PolyType ): Type =
233235 tp.derivedLambdaType(
@@ -446,10 +448,11 @@ import TypeErasure._
446448 * (they will be fully erased in [[ElimErasedValueType ]]).
447449 * If false, they are erased like normal classes.
448450 * @param isConstructor Argument forms part of the type of a constructor
451+ * @param isSymbol If true, the type being erased is the info of a symbol.
449452 * @param wildcardOK Wildcards are acceptable (true when using the erasure
450453 * for computing a signature name).
451454 */
452- class TypeErasure (sourceLanguage : SourceLanguage , semiEraseVCs : Boolean , isConstructor : Boolean , wildcardOK : Boolean ) {
455+ class TypeErasure (sourceLanguage : SourceLanguage , semiEraseVCs : Boolean , isConstructor : Boolean , isSymbol : Boolean , wildcardOK : Boolean ) {
453456
454457 /** The erasure |T| of a type T. This is:
455458 *
@@ -523,7 +526,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
523526 TypeComparer .orType(this (tp1), this (tp2), isErased = true )
524527 case tp : MethodType =>
525528 def paramErasure (tpToErase : Type ) =
526- erasureFn(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK)(tpToErase)
529+ erasureFn(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK)(tpToErase)
527530 val (names, formals0) = if (tp.isErasedMethod) (Nil , Nil ) else (tp.paramNames, tp.paramInfos)
528531 val formals = formals0.mapConserve(paramErasure)
529532 eraseResult(tp.resultType) match {
@@ -567,7 +570,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
567570 val defn .ArrayOf (elemtp) = tp
568571 if (classify(elemtp).derivesFrom(defn.NullClass )) JavaArrayType (defn.ObjectType )
569572 else if (isUnboundedGeneric(elemtp) && ! sourceLanguage.isJava) defn.ObjectType
570- else JavaArrayType (erasureFn(sourceLanguage, semiEraseVCs = false , isConstructor, wildcardOK)(elemtp))
573+ else JavaArrayType (erasureFn(sourceLanguage, semiEraseVCs = false , isConstructor, isSymbol, wildcardOK)(elemtp))
571574 }
572575
573576 private def erasePair (tp : Type )(using Context ): Type = {
@@ -608,7 +611,9 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
608611 val genericUnderlying = unbox.info.resultType
609612 val underlying = tp.select(unbox).widen.resultType
610613
611- val erasedUnderlying = erasure(underlying)
614+ // The underlying part of an ErasedValueType cannot be an ErasedValueType itself
615+ val erase = erasureFn(sourceLanguage, semiEraseVCs = false , isConstructor, isSymbol, wildcardOK)
616+ val erasedUnderlying = erase(underlying)
612617
613618 // Ideally, we would just use `erasedUnderlying` as the erasure of `tp`, but to
614619 // be binary-compatible with Scala 2 we need two special cases for polymorphic
@@ -646,7 +651,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
646651 // correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the result type of a
647652 // constructor method should not be semi-erased.
648653 if semiEraseVCs && isConstructor && ! tp.isInstanceOf [MethodOrPoly ] then
649- erasureFn(sourceLanguage, semiEraseVCs = false , isConstructor, wildcardOK).eraseResult(tp)
654+ erasureFn(sourceLanguage, semiEraseVCs = false , isConstructor, isSymbol, wildcardOK).eraseResult(tp)
650655 else tp match
651656 case tp : TypeRef =>
652657 val sym = tp.symbol
0 commit comments