Skip to content

Commit 04bbfe7

Browse files
committed
Erase phantom fields.
1 parent 5256547 commit 04bbfe7

File tree

8 files changed

+150
-0
lines changed

8 files changed

+150
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
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 ExpandPrivate, // Widen private definitions accessed from nested classes
Lines changed: 59 additions & 0 deletions
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+
}

tests/run/phantom-lazy-val.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
1
2+
foo
3+
2

tests/run/phantom-lazy-val.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
/* Run this test with
3+
* `run tests/run/xyz.scala -Xprint-diff-del -Xprint:arrayConstructors,phantomTermErasure,phantomTypeErasure,erasure`
4+
* to see the the diffs after PhantomRefErasure, PhantomDeclErasure and Erasure.
5+
*/
6+
7+
object Test {
8+
import Boo._
9+
10+
def main(args: Array[String]): Unit = {
11+
println(1)
12+
foo
13+
println(2)
14+
foo
15+
}
16+
17+
lazy val foo = {
18+
println("foo")
19+
any
20+
}
21+
22+
}
23+
24+
object Boo extends Phantom {
25+
type BooAny = this.Any
26+
def any: BooAny = assume[BooAny]
27+
}

tests/run/phantom-val.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo
2+
1

tests/run/phantom-val.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
/* Run this test with
3+
* `run tests/run/xyz.scala -Xprint-diff-del -Xprint:arrayConstructors,phantomTermErasure,phantomTypeErasure,erasure`
4+
* to see the the diffs after PhantomRefErasure, PhantomDeclErasure and Erasure.
5+
*/
6+
7+
object Test {
8+
import Boo._
9+
10+
def main(args: Array[String]): Unit = {
11+
println(1)
12+
foo
13+
foo
14+
15+
}
16+
17+
val foo = {
18+
println("foo")
19+
any
20+
}
21+
}
22+
23+
object Boo extends Phantom {
24+
type BooAny = this.Any
25+
def any: BooAny = assume[BooAny]
26+
}

tests/run/phantom-var.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo
2+
foo2

tests/run/phantom-var.scala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
/* Run this test with
3+
* `run tests/run/xyz.scala -Xprint-diff-del -Xprint:arrayConstructors,phantomTermErasure,phantomTypeErasure,erasure`
4+
* to see the the diffs after PhantomRefErasure, PhantomDeclErasure and Erasure.
5+
*/
6+
7+
object Test {
8+
import Boo._
9+
10+
def main(args: Array[String]): Unit = {
11+
foo
12+
foo
13+
foo = {
14+
println("foo2")
15+
any
16+
}
17+
foo
18+
19+
}
20+
21+
var foo = {
22+
println("foo")
23+
any
24+
}
25+
}
26+
27+
object Boo extends Phantom {
28+
type BooAny = this.Any
29+
def any: BooAny = assume[BooAny]
30+
}

0 commit comments

Comments
 (0)