@@ -5,11 +5,13 @@ package core
5
5
import Symbols ._ , Types ._ , Contexts ._ , Flags ._ , Names ._ , StdNames ._ , Decorators ._ , Flags .JavaDefined
6
6
import Uniques .unique
7
7
import dotc .transform .ExplicitOuter ._
8
+ import dotc .transform .ValueClasses ._
8
9
import typer .Mode
9
10
import util .DotClass
10
11
11
12
/** Erased types are:
12
13
*
14
+ * ErasedValueType
13
15
* TypeRef(prefix is ignored, denot is ClassDenotation)
14
16
* TermRef(prefix is ignored, denot is SymDenotation)
15
17
* JavaArrayType
@@ -30,8 +32,12 @@ object TypeErasure {
30
32
31
33
/** A predicate that tests whether a type is a legal erased type. Only asInstanceOf and
32
34
* isInstanceOf may have types that do not satisfy the predicate.
35
+ * ErasedValueType is considered an erased type because it is valid after Erasure (it is
36
+ * eliminated by ElimErasedValueType).
33
37
*/
34
38
def isErasedType (tp : Type )(implicit ctx : Context ): Boolean = tp match {
39
+ case _ : ErasedValueType =>
40
+ true
35
41
case tp : TypeRef =>
36
42
tp.symbol.isClass && tp.symbol != defn.AnyClass
37
43
case _ : TermRef =>
@@ -283,10 +289,12 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
283
289
* - For any other type, exception.
284
290
*/
285
291
private def apply (tp : Type )(implicit ctx : Context ): Type = tp match {
292
+ case _ : ErasedValueType =>
293
+ tp
286
294
case tp : TypeRef =>
287
295
val sym = tp.symbol
288
296
if (! sym.isClass) this (tp.info)
289
- else if (sym. isDerivedValueClass) eraseDerivedValueClassRef(tp)
297
+ else if (semiEraseVCs && isDerivedValueClass(sym) ) eraseDerivedValueClassRef(tp)
290
298
else eraseNormalClassRef(tp)
291
299
case tp : RefinedType =>
292
300
val parent = tp.parent
@@ -295,7 +303,9 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
295
303
case tp : TermRef =>
296
304
this (tp.widen)
297
305
case tp : ThisType =>
298
- this (tp.cls.typeRef)
306
+ def thisTypeErasure (tpToErase : Type ) =
307
+ erasureFn(isJava, semiEraseVCs = false , isConstructor, wildcardOK)(tpToErase)
308
+ thisTypeErasure(tp.cls.typeRef)
299
309
case SuperType (thistpe, supertpe) =>
300
310
SuperType (this (thistpe), this (supertpe))
301
311
case ExprType (rt) =>
@@ -307,7 +317,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
307
317
case OrType (tp1, tp2) =>
308
318
ctx.typeComparer.orType(this (tp1), this (tp2), erased = true )
309
319
case tp : MethodType =>
310
- val paramErasure = erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(_)
320
+ def paramErasure (tpToErase : Type ) =
321
+ erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(tpToErase)
311
322
val formals = tp.paramTypes.mapConserve(paramErasure)
312
323
eraseResult(tp.resultType) match {
313
324
case rt : MethodType =>
@@ -345,9 +356,11 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
345
356
346
357
private def eraseArray (tp : RefinedType )(implicit ctx : Context ) = {
347
358
val defn .ArrayType (elemtp) = tp
359
+ def arrayErasure (tpToErase : Type ) =
360
+ erasureFn(isJava, semiEraseVCs = false , isConstructor, wildcardOK)(tpToErase)
348
361
if (elemtp derivesFrom defn.NullClass ) JavaArrayType (defn.ObjectType )
349
362
else if (isUnboundedGeneric(elemtp)) defn.ObjectType
350
- else JavaArrayType (this (elemtp))
363
+ else JavaArrayType (arrayErasure (elemtp))
351
364
}
352
365
353
366
/** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s are
@@ -365,8 +378,12 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
365
378
case tp => this (tp)
366
379
}
367
380
368
- private def eraseDerivedValueClassRef (tref : TypeRef )(implicit ctx : Context ): Type =
369
- unsupported(" eraseDerivedValueClass" )
381
+ private def eraseDerivedValueClassRef (tref : TypeRef )(implicit ctx : Context ): Type = {
382
+ val cls = tref.symbol.asClass
383
+ val underlying = underlyingOfValueClass(cls)
384
+ ErasedValueType (cls, erasure(underlying))
385
+ }
386
+
370
387
371
388
private def eraseNormalClassRef (tref : TypeRef )(implicit ctx : Context ): Type = {
372
389
val cls = tref.symbol.asClass
@@ -378,7 +395,10 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
378
395
case tp : TypeRef =>
379
396
val sym = tp.typeSymbol
380
397
if (sym eq defn.UnitClass ) sym.typeRef
381
- else if (sym.isDerivedValueClass) eraseNormalClassRef(tp)
398
+ // For a value class V, "new V(x)" should have type V for type adaptation to work
399
+ // correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the return type of a
400
+ // constructor method should not be semi-erased.
401
+ else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp)
382
402
else this (tp)
383
403
case RefinedType (parent, _) if ! (parent isRef defn.ArrayClass ) =>
384
404
eraseResult(parent)
@@ -400,10 +420,12 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
400
420
* Need to ensure correspondence with erasure!
401
421
*/
402
422
private def sigName (tp : Type )(implicit ctx : Context ): TypeName = tp match {
423
+ case ErasedValueType (_, underlying) =>
424
+ sigName(underlying)
403
425
case tp : TypeRef =>
404
426
val sym = tp.symbol
405
427
if (! sym.isClass) sigName(tp.info)
406
- else if (sym. isDerivedValueClass) sigName(eraseDerivedValueClassRef(tp))
428
+ else if (isDerivedValueClass(sym) ) sigName(eraseDerivedValueClassRef(tp))
407
429
else normalizeClass(sym.asClass).fullName.asTypeName
408
430
case defn.ArrayType (elem) =>
409
431
sigName(this (tp))
0 commit comments