Skip to content

Commit 2c991c0

Browse files
committed
Erase phantom fields.
Erase all `val` and `var` of phantom type. `lazy val` are not transformed as their expansion is done in the backend. Erasure: * Assignments are replaced by their RHS * Local `val` and `var` definitions are replaced by their RHS * Fields are removed * Getters return `null.asInstanceOf[dotty.runtime.ErasedPhantom]` Tests for this commit where added in `Extra tests for Phantoms 2`, they where back ported as the semantics and runtime is not affected.
1 parent 8436d52 commit 2c991c0

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class Compiler {
9494
List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
9595
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
9696
new ElimStaticThis, // Replace `this` references to static objects by global identifiers
97+
new PhantomVals, // Remove ValDefs of phantom type
9798
new Flatten, // Lift all inner classes to package scope
9899
new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group
99100
List(new MoveStatics, // Move static methods to companion classes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import DenotTransformers._
6+
import Phases.Phase
7+
import Contexts.Context
8+
import Symbols._
9+
import Constants._
10+
import TreeTransforms._
11+
import Flags._
12+
13+
/** Erases all ValDefs of phantom type,
14+
* except for `lazy val` as the field are not yet generated.
15+
*
16+
* <accessor> <mods> def x(): ErasedPhantom = e
17+
* --> <accessor> <mods> def x(): ErasedPhantom = null
18+
*
19+
*
20+
* x = e --> e where type of x is ErasedPhantom
21+
*
22+
* Filed in class
23+
* <private> <mods> val x: ErasedPhantom --> EmptyTree
24+
*
25+
* Field in method
26+
* <mods> val x: ErasedPhantom = e --> e
27+
*/
28+
class PhantomVals extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
29+
import ast.tpd._
30+
31+
override def phaseName = "phantomVals"
32+
33+
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
34+
// TODO
35+
}
36+
37+
override def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set(classOf[Constructors])
38+
39+
override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
40+
val sym = tree.symbol
41+
if (sym.is(Lazy) || !(tree.tpt.tpe =:= defn.ErasedPhantomType)) tree
42+
else if (sym.is(Private)) EmptyTree
43+
else tree.rhs
44+
}
45+
46+
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
47+
val sym = tree.symbol
48+
if (sym.isGetter && !sym.is(Lazy) && (tree.tpt.tpe =:= defn.ErasedPhantomType)) {
49+
cpy.DefDef(tree)(rhs = Literal(Constant(null)).withType(defn.ErasedPhantomType))
50+
} else tree
51+
}
52+
53+
override def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = {
54+
val lhsSym = tree.lhs.symbol
55+
if (!lhsSym.is(Lazy) && tree.rhs.tpe =:= defn.ErasedPhantomType) tree.rhs
56+
else tree
57+
}
58+
59+
}

0 commit comments

Comments
 (0)