Skip to content

Commit 67f2854

Browse files
committed
New phase: ElimErasedValueType
This phase erases ErasedValueType to their underlying type, in scalac this was done in PostErasure.
1 parent b736261 commit 67f2854

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ class Compiler {
5757
new ElimByName,
5858
new ResolveSuper),
5959
List(new Erasure),
60-
List(new Mixin,
60+
List(new ElimErasedValueType,
61+
new Mixin,
6162
new Memoize,
6263
new CapturedVars,
6364
new Constructors,
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import ast.{Trees, tpd}
5+
import core._, core.Decorators._
6+
import TreeTransforms._, Phases.Phase
7+
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
8+
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
9+
import TypeErasure.ErasedValueType, ValueClasses._
10+
11+
/** This phase erases ErasedValueType to their underlying type.
12+
* It also removes the synthetic cast methods u2evt$ and evt2u$ which are
13+
* no longer needed afterwards.
14+
*/
15+
class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer {
16+
17+
import tpd._
18+
19+
override def phaseName: String = "elimErasedValueType"
20+
21+
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure])
22+
23+
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = sym match {
24+
case sym: ClassSymbol if sym is ModuleClass =>
25+
sym.companionClass match {
26+
case origClass: ClassSymbol if isDerivedValueClass(origClass) =>
27+
val cinfo = tp.asInstanceOf[ClassInfo]
28+
val decls1 = cinfo.decls.cloneScope
29+
ctx.atPhase(this.next) { implicit ctx =>
30+
// Remove synthetic cast methods introduced by ExtensionMethods,
31+
// they are no longer needed after this phase.
32+
decls1.unlink(cinfo.decl(nme.U2EVT).symbol)
33+
decls1.unlink(cinfo.decl(nme.EVT2U).symbol)
34+
}
35+
cinfo.derivedClassInfo(decls = decls1)
36+
case _ =>
37+
tp
38+
}
39+
case _ =>
40+
elimEVT(tp)
41+
}
42+
43+
def elimEVT(tp: Type)(implicit ctx: Context): Type = tp match {
44+
case ErasedValueType(_, underlying) =>
45+
elimEVT(underlying)
46+
case tp: MethodType =>
47+
val paramTypes = tp.paramTypes.mapConserve(elimEVT)
48+
val retType = elimEVT(tp.resultType)
49+
tp.derivedMethodType(tp.paramNames, paramTypes, retType)
50+
case _ =>
51+
tp
52+
}
53+
54+
def transformTypeOfTree(tree: Tree)(implicit ctx: Context): Tree =
55+
tree.withType(elimEVT(tree.tpe))
56+
57+
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
58+
val Apply(fun, args) = tree
59+
val name = fun.symbol.name
60+
61+
// The casts to and from ErasedValueType are no longer needed once ErasedValueType
62+
// has been eliminated.
63+
val t =
64+
if ((name eq nme.U2EVT) || (name eq nme.EVT2U))
65+
args.head
66+
else
67+
tree
68+
transformTypeOfTree(t)
69+
}
70+
71+
// FIXME: transformIf and transformBlock won't be required anymore once #444 is fixed.
72+
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree =
73+
transformTypeOfTree(tree)
74+
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
75+
transformTypeOfTree(tree)
76+
override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree =
77+
transformTypeOfTree(tree)
78+
override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo): Tree =
79+
transformTypeOfTree(tree)
80+
override def transformTypeTree(tree: TypeTree)(implicit ctx: Context, info: TransformerInfo): Tree =
81+
transformTypeOfTree(tree)
82+
}

0 commit comments

Comments
 (0)