From 5dec4ce8a64d44ee602c09d468414b13eecba389 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 18 Mar 2015 23:56:19 +0100 Subject: Erasure: properly erase value classes There are three ways to erase a value class: - In most case, it should be semi-erased to an ErasedValueType, which will be fully erased to its underlying type in ElimErasedValueType. This corresponds to semiEraseVCs = true in TypeErasure. - In a few cases, it should be erased like a normal class, so far this seems to be necessary for: * The return type of a constructor * The underlying type of a ThisType * TypeTree nodes inside New nodes * TypeApply nodes * Arrays In these cases, we set semiEraseVCs = false - When calling `sigName` it should be erased to its underlying type. This commit implements all these cases. Note that this breaks most tests because ElimErasedValueType has not been implemented yet, it is part of the next commit. --- src/dotty/tools/dotc/transform/Erasure.scala | 37 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'src/dotty/tools/dotc/transform/Erasure.scala') diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 01f86915d..293059af2 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -254,18 +254,39 @@ object Erasure extends TypeTestsCasts{ class Typer extends typer.ReTyper with NoChecking { import Boxing._ - def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = tree.typeOpt match { - case tp: TermRef if tree.isTerm => erasedRef(tp) - case tp => erasure(tp) - } + def erasedType(tree: untpd.Tree, semiEraseVCs: Boolean = true)(implicit ctx: Context): Type = + tree.typeOpt match { + case tp: TermRef if tree.isTerm => erasedRef(tp) + case tp => erasure(tp, semiEraseVCs) + } - override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { + def promote(tree: untpd.Tree, semiEraseVCs: Boolean)(implicit ctx: Context): tree.ThisTree[Type] = { assert(tree.hasType) - val erased = erasedType(tree) + val erased = erasedType(tree, semiEraseVCs) ctx.log(s"promoting ${tree.show}: ${erased.showWithUnderlying()}") tree.withType(erased) } + override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { + promote(tree, true) + } + + /** When erasing most TypeTrees we should not semi-erase value types. + * This is not the case for [[DefDef#tpt]], [[ValDef#tpt]] and [[Typed#tpt]], they + * are handled separately by [[typedDefDef]], [[typedValDef]] and [[typedTyped]]. + */ + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = { + promote(tree, semiEraseVCs = false) + } + + /** 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 expr1 = typed(expr, tpt1.tpe) + assignType(untpd.cpy.Typed(tree)(expr1, tpt1), tpt1) + } + override def typedLiteral(tree: untpd.Literal)(implicit ctc: Context): Literal = if (tree.typeOpt.isRef(defn.UnitClass)) tree.withType(tree.typeOpt) else super.typedLiteral(tree) @@ -330,7 +351,7 @@ object Erasure extends TypeTestsCasts{ assert(sym.isConstructor, s"${sym.showLocated}") select(qual, defn.ObjectClass.info.decl(sym.name).symbol) } - else if (qualIsPrimitive && !symIsPrimitive || qual.tpe.isErasedValueType) + else if (qualIsPrimitive && !symIsPrimitive || qual.tpe.widenDealias.isErasedValueType) recur(box(qual)) else if (!qualIsPrimitive && symIsPrimitive) recur(unbox(qual, sym.owner.typeRef)) @@ -349,7 +370,7 @@ object Erasure extends TypeTestsCasts{ } override def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context) = - untpd.Ident(tree.name).withPos(tree.pos).withType(erasedType(tree)) + untpd.Ident(tree.name).withPos(tree.pos).withType(erasedType(tree, semiEraseVCs = false)) override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = if (tree.symbol == ctx.owner.enclosingClass || tree.symbol.isStaticOwner) promote(tree) -- cgit v1.2.3