Skip to content

Commit 017b421

Browse files
committed
Add documentation.
1 parent 43a332e commit 017b421

File tree

5 files changed

+35
-5
lines changed

5 files changed

+35
-5
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dotty.tools.dotc.core
2+
3+
import dotty.tools.dotc.ast.tpd._
4+
import dotty.tools.dotc.core.Contexts.Context
5+
import dotty.tools.dotc.core.Symbols.defn
6+
import dotty.tools.dotc.core.Types.Type
7+
8+
/** Phantom erasure erases (minimal erasure):
9+
*
10+
* - Parameters/arguments are erased to BoxedUnit. The next step will remove the parameters
11+
* 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. The next step
13+
* is to erase the fields for phantom types (implemented in branch implement-phantom-types-part-3)
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.
19+
*/
20+
object PhantomErasure {
21+
22+
/** Returns the default erased type of a phantom type */
23+
def erasedPhantomType(implicit ctx: Context): Type = defn.BoxedUnitType
24+
25+
/** Returns the default erased tree for a call to Phantom.assume */
26+
def erasedAssume(implicit ctx: Context): Tree = ref(defn.BoxedUnit_UNIT)
27+
28+
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
364364
else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClassRef(tp)
365365
else if (sym == defn.ArrayClass) apply(tp.appliedTo(TypeBounds.empty)) // i966 shows that we can hit a raw Array type.
366366
else if (defn.isSyntheticFunctionClass(sym)) defn.erasedFunctionType(sym)
367-
else if (defn.isPhantomTerminalClass(tp.symbol)) defn.BoxedUnitType
367+
else if (defn.isPhantomTerminalClass(tp.symbol)) PhantomErasure.erasedPhantomType
368368
else eraseNormalClassRef(tp)
369369
case tp: RefinedType =>
370370
val parent = tp.parent
@@ -404,6 +404,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
404404
case tr :: trs1 =>
405405
assert(!tr.classSymbol.is(Trait), cls)
406406
val tr1 = if (cls is Trait) defn.ObjectType else tr
407+
// We remove the Phantom trait to erase the definitions of Phantom.{assume, Any, Nothing}
407408
tr1 :: trs1.filterNot(x => x.isRef(defn.ObjectClass) || x.isRef(defn.PhantomClass))
408409
case nil => nil
409410
}
@@ -508,7 +509,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
508509
if (defn.isSyntheticFunctionClass(sym))
509510
sigName(defn.erasedFunctionType(sym))
510511
else if (defn.isPhantomTerminalClass(tp.symbol))
511-
sigName(defn.BoxedUnitType)
512+
sigName(PhantomErasure.erasedPhantomType)
512513
else
513514
normalizeClass(sym.asClass).fullName.asTypeName
514515
case defn.ArrayOf(elem) =>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ object Types {
201201
else defn.NothingType
202202
}
203203

204-
/** Returns the type of the lattice (i.e. the prefix of the phantom type)
204+
/** Returns the type of the phantom lattice (i.e. the prefix of the phantom type)
205205
* - XYZ if XYZ extends scala.Phantom and this type is upper bounded XYZ.Any
206206
* - NoType otherwise
207207
*/

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import core.Decorators._
2323
import dotty.tools.dotc.ast.{Trees, tpd, untpd}
2424
import ast.Trees._
2525
import scala.collection.mutable.ListBuffer
26-
import dotty.tools.dotc.core.{Constants, Flags}
26+
import core.{Constants, Flags, Mode, PhantomErasure}
2727
import ValueClasses._
2828
import TypeUtils._
2929
import ExplicitOuter._
@@ -455,7 +455,7 @@ object Erasure extends TypeTestsCasts{
455455
if (fun.symbol == defn.cbnArg)
456456
typedUnadapted(args.head, pt)
457457
else if (fun.symbol eq defn.Phantom_assume)
458-
ref(defn.BoxedUnit_UNIT)
458+
PhantomErasure.erasedAssume
459459
else typedExpr(fun, FunProto(args, pt, this)) match {
460460
case fun1: Apply => // arguments passed in prototype were already passed
461461
fun1

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
13481348
cls, isRequired, cdef.pos)
13491349
}
13501350

1351+
// Check that phantom lattices are defined in an `object`
13511352
if (cls.classParents.exists(_.classSymbol eq defn.PhantomClass)) {
13521353
if (!cls.is(Module))
13531354
ctx.error("Only object can extend scala.Phantom", cdef.pos)

0 commit comments

Comments
 (0)