Skip to content

Commit 7c6232e

Browse files
committed
Add TypeErasure#isSymbol, true when erasing a symbol info
This will be used in the next commit to deal with Scala.js unions. Also change the erasure of value classes to use `this(...)` instead of `erasure(...)` for the underlying type, otherwise flags like `isSymbol` woudln't be propagated.
1 parent 9fc91d8 commit 7c6232e

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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,7 @@ 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+
val erasedUnderlying = this(underlying)
612615

613616
// Ideally, we would just use `erasedUnderlying` as the erasure of `tp`, but to
614617
// be binary-compatible with Scala 2 we need two special cases for polymorphic
@@ -646,7 +649,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
646649
// correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the result type of a
647650
// constructor method should not be semi-erased.
648651
if semiEraseVCs && isConstructor && !tp.isInstanceOf[MethodOrPoly] then
649-
erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, wildcardOK).eraseResult(tp)
652+
erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, isSymbol, wildcardOK).eraseResult(tp)
650653
else tp match
651654
case tp: TypeRef =>
652655
val sym = tp.symbol

0 commit comments

Comments
 (0)