Skip to content

TypeErasure#erasure: do not semi-erase types by default #680

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,14 @@ object TypeErasure {
private def erasureCtx(implicit ctx: Context) =
if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase).addMode(Mode.FutureDefsOK) else ctx

def erasure(tp: Type, semiEraseVCs: Boolean = true)(implicit ctx: Context): Type =
/** The standard erasure of a Scala type.
*
* @param tp The type to erase.
* @param semiEraseVCs If true, value classes are semi-erased to ErasedValueType
* (they will be fully erased in [[ElimErasedValueType]]).
* If false, they are erased like normal classes.
*/
def erasure(tp: Type, semiEraseVCs: Boolean = false)(implicit ctx: Context): Type =
erasureFn(isJava = false, semiEraseVCs, isConstructor = false, wildcardOK = false)(tp)(erasureCtx)

def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = {
Expand All @@ -134,7 +141,7 @@ object TypeErasure {
case tp: ThisType =>
tp
case tp =>
erasure(tp)
erasure(tp, semiEraseVCs = true)
}

/** The symbol's erased info. This is the type's erasure, except for the following symbols:
Expand Down Expand Up @@ -389,7 +396,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type = {
val cls = tref.symbol.asClass
val underlying = underlyingOfValueClass(cls)
ErasedValueType(cls, erasure(underlying))
ErasedValueType(cls, erasure(underlying, semiEraseVCs = true))
}


Expand Down
39 changes: 19 additions & 20 deletions src/dotty/tools/dotc/transform/ClassOf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import core.Symbols.TermSymbol
import core.TypeErasure
import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform}

/** Performs rewritings as follows for `classOf` calls:
* classOf[CustomValueClass] ~> CustomValueClass class
* classOf[ValueClass] ~> ValueClass class, where ValueClass is Boolean, Byte, Short, etc.
* classOf[AnyOtherClass] ~> erasure(AnyOtherClass)
/** Rewrite `classOf` calls as follow:
*
* For every primitive class C whose boxed class is called B:
* classOf[C] -> B.TYPE
* For every non-primitive class D:
* classOf[D] -> Literal(Constant(erasure(D)))
*/
class ClassOf extends MiniPhaseTransform {
import tpd._
Expand All @@ -32,22 +34,19 @@ class ClassOf extends MiniPhaseTransform {
val tp = tree.args.head.tpe
val defn = ctx.definitions
val claz = tp.classSymbol
if (ValueClasses.isDerivedValueClass(claz)) {
Literal(Constant(ref(claz).tpe))
} else {
def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe)
claz match {
case defn.BooleanClass => TYPE(defn.BoxedBooleanModule)
case defn.ByteClass => TYPE(defn.BoxedByteModule)
case defn.ShortClass => TYPE(defn.BoxedShortModule)
case defn.CharClass => TYPE(defn.BoxedCharModule)
case defn.IntClass => TYPE(defn.BoxedIntModule)
case defn.LongClass => TYPE(defn.BoxedLongModule)
case defn.FloatClass => TYPE(defn.BoxedFloatModule)
case defn.DoubleClass => TYPE(defn.BoxedDoubleModule)
case defn.UnitClass => TYPE(defn.BoxedVoidModule)
case _ => Literal(Constant(TypeErasure.erasure(tp)))
}

def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe)
claz match {
case defn.BooleanClass => TYPE(defn.BoxedBooleanModule)
case defn.ByteClass => TYPE(defn.BoxedByteModule)
case defn.ShortClass => TYPE(defn.BoxedShortModule)
case defn.CharClass => TYPE(defn.BoxedCharModule)
case defn.IntClass => TYPE(defn.BoxedIntModule)
case defn.LongClass => TYPE(defn.BoxedLongModule)
case defn.FloatClass => TYPE(defn.BoxedFloatModule)
case defn.DoubleClass => TYPE(defn.BoxedDoubleModule)
case defn.UnitClass => TYPE(defn.BoxedVoidModule)
case _ => Literal(Constant(TypeErasure.erasure(tp)))
}
} else tree
}
Expand Down
6 changes: 3 additions & 3 deletions src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ object Erasure extends TypeTestsCasts{
class Typer extends typer.ReTyper with NoChecking {
import Boxing._

def erasedType(tree: untpd.Tree, semiEraseVCs: Boolean = true)(implicit ctx: Context): Type =
def erasedType(tree: untpd.Tree, semiEraseVCs: Boolean)(implicit ctx: Context): Type =
tree.typeOpt match {
case tp: TermRef if tree.isTerm => erasedRef(tp)
case tp => erasure(tp, semiEraseVCs)
Expand Down Expand Up @@ -296,7 +296,7 @@ object Erasure extends TypeTestsCasts{
/** This override is only needed to semi-erase type ascriptions */
override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = {
val Typed(expr, tpt) = tree
val tpt1 = promote(tpt)
val tpt1 = promote(tpt, semiEraseVCs = true)
val expr1 = typed(expr, tpt1.tpe)
assignType(untpd.cpy.Typed(tree)(expr1, tpt1), tpt1)
}
Expand Down Expand Up @@ -460,7 +460,7 @@ object Erasure extends TypeTestsCasts{
if (pt.isValueType) pt else {
if (tree.typeOpt.derivesFrom(ctx.definitions.UnitClass))
tree.typeOpt
else erasure(tree.typeOpt)
else erasure(tree.typeOpt, semiEraseVCs = true)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/transform/ExtensionMethods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
}
}

val underlying = erasure(underlyingOfValueClass(valueClass))
val underlying = erasure(underlyingOfValueClass(valueClass), semiEraseVCs = true)
val evt = ErasedValueType(valueClass, underlying)
val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT, Synthetic | Method,
MethodType(List(nme.x_0), List(underlying), evt))
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/transform/TypeTestsCasts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ trait TypeTestsCasts {
} else
derivedTree(qual, defn.Any_asInstanceOf, argType)
}
def erasedArg = erasure(tree.args.head.tpe, semiEraseVCs = false)
def erasedArg = erasure(tree.args.head.tpe)
if (sym eq defn.Any_isInstanceOf)
transformIsInstanceOf(qual, erasedArg)
else if (sym eq defn.Any_asInstanceOf)
Expand Down