Skip to content

Commit e639043

Browse files
Merge pull request #2449 from dotty-staging/make-unit-erased-phantom
Use ErasedPhantom instead of BoxedUnit as erased unit type.
2 parents 725ca9f + 9e71741 commit e639043

File tree

4 files changed

+49
-15
lines changed

4 files changed

+49
-15
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,4 +990,10 @@ class Definitions {
990990
/** If the symbol is of the class scala.Phantom.Any or scala.Phantom.Nothing */
991991
def isPhantomTerminalClass(sym: Symbol) = (sym eq Phantom_AnyClass) || (sym eq Phantom_NothingClass)
992992

993+
994+
lazy val ErasedPhantomType: TypeRef = ctx.requiredClassRef("dotty.runtime.ErasedPhantom")
995+
def ErasedPhantomClass(implicit ctx: Context) = ErasedPhantomType.symbol.asClass
996+
997+
def ErasedPhantom_UNIT(implicit ctx: Context) = ErasedPhantomClass.linkedClass.requiredValue("UNIT")
998+
993999
}

compiler/src/dotty/tools/dotc/core/PhantomErasure.scala

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,18 @@ import dotty.tools.dotc.core.Types.Type
77

88
/** Phantom erasure erases (minimal erasure):
99
*
10-
* - Parameters/arguments are erased to BoxedUnit. The next step will remove the parameters
10+
* - Parameters/arguments are erased to ErasedPhantom. The next step will remove the parameters
1111
* from the method definitions and calls (implemented in branch implement-phantom-types-part-2).
12-
* - Definitions of `def`, `val`, `lazy val` and `var` returning a phantom type to return a BoxedUnit. Where fields
13-
* with BoxedUnit type are not memoized (see transform/Memoize.scala).
14-
* - Calls to Phantom.assume become calls to BoxedUnit. Intended to be optimized away by local optimizations.
15-
*
16-
* BoxedUnit is used as it fits perfectly and homogeneously in all locations where phantoms can be found.
17-
* Additionally some of the optimizations that can be performed on phantom types can also be directly implemented
18-
* on all boxed units.
12+
* - Definitions of `def`, `val`, `lazy val` and `var` returning a phantom type to return a ErasedPhantom. Where fields
13+
* with ErasedPhantom type are not memoized (see transform/Memoize.scala).
14+
* - Calls to Phantom.assume become calls to ErasedPhantom.UNIT. Intended to be optimized away by local optimizations.
1915
*/
2016
object PhantomErasure {
2117

2218
/** Returns the default erased type of a phantom type */
23-
def erasedPhantomType(implicit ctx: Context): Type = defn.BoxedUnitType
19+
def erasedPhantomType(implicit ctx: Context): Type = defn.ErasedPhantomType
2420

2521
/** Returns the default erased tree for a call to Phantom.assume */
26-
def erasedAssume(implicit ctx: Context): Tree = ref(defn.BoxedUnit_UNIT)
22+
def erasedAssume(implicit ctx: Context): Tree = ref(defn.ErasedPhantom_UNIT)
2723

2824
}

compiler/src/dotty/tools/dotc/transform/Memoize.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,19 @@ import Decorators._
9999
val NoFieldNeeded = Lazy | Deferred | JavaDefined | (if (ctx.settings.YnoInline.value) EmptyFlags else Inline)
100100

101101
def isErasableBottomField(cls: Symbol): Boolean = {
102-
// TODO: For Scala.js, return false if this field is in a js.Object unless it was a Phantom before erasure.
103-
// Could time travel to detect phantom types or add an annotation before erasure.
104-
!field.isVolatile && ((cls eq defn.NothingClass) || (cls eq defn.NullClass) || (cls eq defn.BoxedUnitClass))
102+
// TODO: For Scala.js, return false if this field is in a js.Object unless it is an ErasedPhantomClass.
103+
!field.isVolatile &&
104+
((cls eq defn.NothingClass) || (cls eq defn.NullClass) || (cls eq defn.BoxedUnitClass) || (cls eq defn.ErasedPhantomClass))
105105
}
106106

107107
def erasedBottomTree(sym: Symbol) = {
108108
if (sym eq defn.NothingClass) Throw(Literal(Constant(null)))
109109
else if (sym eq defn.NullClass) Literal(Constant(null))
110+
else if (sym eq defn.BoxedUnitClass) ref(defn.BoxedUnit_UNIT)
111+
else if (sym eq defn.ErasedPhantomClass) ref(defn.ErasedPhantom_UNIT)
110112
else {
111-
assert(sym eq defn.BoxedUnitClass)
112-
ref(defn.BoxedUnit_UNIT)
113+
assert(false, sym + " has no erased bottom tree")
114+
EmptyTree
113115
}
114116
}
115117

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package dotty.runtime;
2+
3+
4+
/** Unit type representing an erased phantom value.
5+
*
6+
* Based on implementation of BoxedUnit.
7+
*/
8+
public final class ErasedPhantom implements java.io.Serializable {
9+
private static final long serialVersionUID = 4116021023472525845L;
10+
11+
public final static ErasedPhantom UNIT = new ErasedPhantom();
12+
13+
public final static Class<Void> TYPE = java.lang.Void.TYPE;
14+
15+
private Object readResolve() { return UNIT; }
16+
17+
private ErasedPhantom() { }
18+
19+
public boolean equals(java.lang.Object other) {
20+
return this == other;
21+
}
22+
23+
public int hashCode() {
24+
return 0;
25+
}
26+
27+
public String toString() {
28+
return "(\uD83D\uDC7B )";
29+
}
30+
}

0 commit comments

Comments
 (0)