diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2015-03-18 23:56:19 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-05-01 13:26:23 +0200 |
commit | 5dec4ce8a64d44ee602c09d468414b13eecba389 (patch) | |
tree | 3df31764445c447029d2114e25c95d83a60e4c0a /src/dotty/tools/dotc/transform/Erasure.scala | |
parent | 391c80c4dfb2489e4098af33265b22332ef3d5f1 (diff) | |
download | dotty-5dec4ce8a64d44ee602c09d468414b13eecba389.tar.gz dotty-5dec4ce8a64d44ee602c09d468414b13eecba389.tar.bz2 dotty-5dec4ce8a64d44ee602c09d468414b13eecba389.zip |
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.
Diffstat (limited to 'src/dotty/tools/dotc/transform/Erasure.scala')
-rw-r--r-- | src/dotty/tools/dotc/transform/Erasure.scala | 37 |
1 files changed, 29 insertions, 8 deletions
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) |