Skip to content

Commit

Permalink
Merge pull request #3410 from dotty-staging/make-phantoms-unused
Browse files Browse the repository at this point in the history
Remove scala.Phantom (replaced by `unused`)
  • Loading branch information
odersky authored Mar 1, 2018
2 parents bedbd5a + 23b61fa commit 4d41e4f
Show file tree
Hide file tree
Showing 141 changed files with 74 additions and 2,208 deletions.
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ class Compiler {
new ShortcutImplicits, // Allow implicit functions without creating closures
new CrossCastAnd, // Normalize selections involving intersection types.
new Splitter) :: // Expand selections involving union types into conditionals
List(new PhantomArgLift, // Extracts the evaluation of phantom arguments placing them before the call.
new UnusedDecls, // Removes all unused defs and vals decls (except for parameters)
List(new UnusedDecls, // Removes all unused defs and vals decls (except for parameters)
new VCInlineMethods, // Inlines calls to value class methods
new SeqLiterals, // Express vararg arguments as arrays
new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods
Expand Down
27 changes: 1 addition & 26 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1161,8 +1161,7 @@ class Definitions {
NullClass,
NothingClass,
SingletonClass,
EqualsPatternClass,
PhantomClass)
EqualsPatternClass)

lazy val syntheticCoreClasses = syntheticScalaClasses ++ List(
EmptyPackageVal,
Expand Down Expand Up @@ -1191,28 +1190,4 @@ class Definitions {
}
}

// ----- Phantoms ---------------------------------------------------------

lazy val PhantomClass: ClassSymbol = {
val cls = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.Phantom, NoInitsTrait, List(AnyType)))

val any = enterCompleteClassSymbol(cls, tpnme.Any, Protected | Final | NoInitsTrait, Nil)
val nothing = enterCompleteClassSymbol(cls, tpnme.Nothing, Protected | Final | NoInitsTrait, List(any.typeRef))
enterMethod(cls, nme.assume_, ExprType(nothing.typeRef), Protected | Final | Method)

cls
}
lazy val Phantom_AnyClass = PhantomClass.unforcedDecls.find(_.name eq tpnme.Any).asClass
lazy val Phantom_NothingClass = PhantomClass.unforcedDecls.find(_.name eq tpnme.Nothing).asClass
lazy val Phantom_assume = PhantomClass.unforcedDecls.find(_.name eq nme.assume_)

/** If the symbol is of the class scala.Phantom.Any or scala.Phantom.Nothing */
def isPhantomTerminalClass(sym: Symbol) = (sym eq Phantom_AnyClass) || (sym eq Phantom_NothingClass)


lazy val ErasedPhantomType: TypeRef = ctx.requiredClassRef("dotty.runtime.ErasedPhantom")
def ErasedPhantomClass(implicit ctx: Context) = ErasedPhantomType.symbol.asClass

def ErasedPhantom_UNIT(implicit ctx: Context) = ErasedPhantomClass.linkedClass.requiredValue("UNIT")

}
33 changes: 0 additions & 33 deletions compiler/src/dotty/tools/dotc/core/PhantomErasure.scala

This file was deleted.

2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Signature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
* to the parameter part of this signature.
*/
def prepend(params: List[Type], isJava: Boolean)(implicit ctx: Context) =
Signature(params.collect { case p if !p.isPhantom => sigName(p, isJava) } ++ paramsSig, resSig)
Signature(params.map(p => sigName(p, isJava)) ++ paramsSig, resSig)

/** A signature is under-defined if its paramsSig part contains at least one
* `tpnme.Uninstantiated`. Under-defined signatures arise when taking a signature
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ object StdNames {
final val SourceFileATTR: N = "SourceFile"
final val SyntheticATTR: N = "Synthetic"

final val Phantom: N = "Phantom"

// ----- Term names -----------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ object SymDenotations {

/** Is this symbol a class references to which that are supertypes of null? */
final def isNullableClass(implicit ctx: Context): Boolean =
isClass && !isValueClass && !(this is ModuleClass) && symbol != defn.NothingClass && !defn.isPhantomTerminalClass(symbol)
isClass && !isValueClass && !(this is ModuleClass) && symbol != defn.NothingClass

/** Is this definition accessible as a member of tree with type `pre`?
* @param pre The type of the tree from which the selection is made
Expand Down
12 changes: 3 additions & 9 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
private[this] var myAnyClass: ClassSymbol = null
private[this] var myNothingClass: ClassSymbol = null
private[this] var myNullClass: ClassSymbol = null
private[this] var myPhantomNothingClass: ClassSymbol = null
private[this] var myObjectClass: ClassSymbol = null
private[this] var myAnyType: TypeRef = null
private[this] var myNothingType: TypeRef = null
Expand All @@ -67,10 +66,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
if (myNullClass == null) myNullClass = defn.NullClass
myNullClass
}
def PhantomNothingClass = {
if (myPhantomNothingClass == null) myPhantomNothingClass = defn.Phantom_NothingClass
myPhantomNothingClass
}
def ObjectClass = {
if (myObjectClass == null) myObjectClass = defn.ObjectClass
myObjectClass
Expand Down Expand Up @@ -287,7 +282,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
if (recur(info1.alias, tp2)) return true
if (tp1.prefix.isStable) return false
case _ =>
if (tp1 eq NothingType) return tp1 == tp2.bottomType
if (tp1 eq NothingType) return true
}
thirdTry
case tp1: TypeParamRef =>
Expand Down Expand Up @@ -586,9 +581,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case _ => false
}
val sym1 = tp1.symbol
(sym1 eq NothingClass) && tp2.isValueTypeOrLambda && !tp2.isPhantom ||
(sym1 eq NullClass) && isNullable(tp2) ||
(sym1 eq PhantomNothingClass) && tp1.topType == tp2.topType
(sym1 eq NothingClass) && tp2.isValueTypeOrLambda ||
(sym1 eq NullClass) && isNullable(tp2)
}
case tp1 @ AppliedType(tycon1, args1) =>
compareAppliedType1(tp1, tycon1, args1)
Expand Down
9 changes: 1 addition & 8 deletions compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,6 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClassRef(tp)
else if (sym == defn.ArrayClass) apply(tp.appliedTo(TypeBounds.empty)) // i966 shows that we can hit a raw Array type.
else if (defn.isSyntheticFunctionClass(sym)) defn.erasedFunctionType(sym)
else if (defn.isPhantomTerminalClass(sym)) PhantomErasure.erasedPhantomType
else if (sym eq defn.PhantomClass) defn.ObjectType // To erase the definitions of Phantom.{assume, Any, Nothing}
else eraseNormalClassRef(tp)
case tp: AppliedType =>
if (tp.tycon.isRef(defn.ArrayClass)) eraseArray(tp)
Expand All @@ -401,10 +399,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
case tp: MethodType =>
def paramErasure(tpToErase: Type) =
erasureFn(tp.isJavaMethod, semiEraseVCs, isConstructor, wildcardOK)(tpToErase)
val (names, formals0) =
if (tp.isUnusedMethod) (Nil, Nil)
else if (tp.paramInfos.exists(_.isPhantom)) tp.paramNames.zip(tp.paramInfos).filterNot(_._2.isPhantom).unzip
else (tp.paramNames, tp.paramInfos)
val (names, formals0) = if (tp.isUnusedMethod) (Nil, Nil) else (tp.paramNames, tp.paramInfos)
val formals = formals0.mapConserve(paramErasure)
eraseResult(tp.resultType) match {
case rt: MethodType =>
Expand Down Expand Up @@ -527,8 +522,6 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
}
if (defn.isSyntheticFunctionClass(sym))
sigName(defn.erasedFunctionType(sym))
else if (defn.isPhantomTerminalClass(tp.symbol))
sigName(PhantomErasure.erasedPhantomType)
else
normalizeClass(sym.asClass).fullName.asTypeName
case tp: AppliedType =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
case pre: SuperType => toPrefix(pre.thistpe, cls, thiscls)
case _ =>
if (thiscls.derivesFrom(cls) && pre.baseType(thiscls).exists)
if (variance <= 0 && !isLegalPrefix(pre)) range(pre.bottomType, pre)
if (variance <= 0 && !isLegalPrefix(pre)) range(defn.NothingType, pre)
else pre
else if ((pre.termSymbol is Package) && !(thiscls is Package))
toPrefix(pre.select(nme.PACKAGE), cls, thiscls)
Expand Down
53 changes: 6 additions & 47 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,59 +193,18 @@ object Types {
}
}

/** Returns true if the type is a phantom type
* - true if XYZ extends scala.Phantom and this type is upper bounded XYZ.Any
* - false otherwise
*/
final def isPhantom(implicit ctx: Context): Boolean = phantomLatticeType.exists

/** Returns the top type of the lattice
* - XYX.Any if XYZ extends scala.Phantom and this type is upper bounded XYZ.Any
* - scala.Any otherwise
*/
final def topType(implicit ctx: Context): Type = {
val lattice = phantomLatticeType
if (lattice.exists) lattice.select(tpnme.Any)
else defn.AnyType
}

/** Returns the bottom type of the lattice
* - XYZ.Nothing if XYZ extends scala.Phantom and this type is upper bounded XYZ.Any
* - scala.Nothing otherwise
*/
final def bottomType(implicit ctx: Context): Type = {
val lattice = phantomLatticeType
if (lattice.exists) lattice.select(tpnme.Nothing)
else defn.NothingType
}

/** Is this type exactly Nothing (no vars, aliases, refinements etc allowed)? */
def isBottomType(implicit ctx: Context): Boolean = this match {
case tp: TypeRef =>
val sym = tp.symbol
(sym eq defn.NothingClass) || (sym eq defn.Phantom_NothingClass)
case tp: TypeRef => tp.symbol eq defn.NothingClass
case _ => false
}

/** Is this type exactly Any (no vars, aliases, refinements etc allowed)? */
def isTopType(implicit ctx: Context): Boolean = this match {
case tp: TypeRef =>
val sym = tp.symbol
(sym eq defn.AnyClass) || (sym eq defn.Phantom_AnyClass)
case tp: TypeRef => tp.symbol eq defn.AnyClass
case _ => false
}

/** Returns the type of the phantom lattice (i.e. the prefix of the phantom type)
* - XYZ if XYZ extends scala.Phantom and this type is upper bounded XYZ.Any
* - NoType otherwise
*/
private final def phantomLatticeType(implicit ctx: Context): Type = widen match {
case tp: ClassInfo if defn.isPhantomTerminalClass(tp.classSymbol) => tp.prefix
case tp: TypeProxy => tp.underlying.phantomLatticeType
case tp: AndOrType => tp.tp1.phantomLatticeType
case _ => NoType
}

/** Is this type a (possibly aliased) singleton type? */
def isSingleton(implicit ctx: Context) = dealias.isInstanceOf[SingletonType]

Expand Down Expand Up @@ -2860,7 +2819,7 @@ object Types {
val dropDependencies = new ApproximatingTypeMap {
def apply(tp: Type) = tp match {
case tp @ TermParamRef(thisLambdaType, _) =>
range(tp.bottomType, atVariance(1)(apply(tp.underlying)))
range(defn.NothingType, atVariance(1)(apply(tp.underlying)))
case _ => mapOver(tp)
}
}
Expand Down Expand Up @@ -4177,7 +4136,7 @@ object Types {
case Range(infoLo: TypeBounds, infoHi: TypeBounds) =>
assert(variance == 0)
if (!infoLo.isAlias && !infoHi.isAlias) propagate(infoLo, infoHi)
else range(tp.bottomType, tp.parent)
else range(defn.NothingType, tp.parent)
case Range(infoLo, infoHi) =>
propagate(infoLo, infoHi)
case _ =>
Expand Down Expand Up @@ -4209,7 +4168,7 @@ object Types {
else tp.derivedTypeBounds(lo, hi)

override protected def derivedSuperType(tp: SuperType, thistp: Type, supertp: Type) =
if (isRange(thistp) || isRange(supertp)) range(thistp.bottomType, thistp.topType)
if (isRange(thistp) || isRange(supertp)) range(defn.NothingType, defn.AnyType)
else tp.derivedSuperType(thistp, supertp)

override protected def derivedAppliedType(tp: AppliedType, tycon: Type, args: List[Type]): Type =
Expand Down Expand Up @@ -4246,7 +4205,7 @@ object Types {
if (distributeArgs(args, tp.typeParams))
range(tp.derivedAppliedType(tycon, loBuf.toList),
tp.derivedAppliedType(tycon, hiBuf.toList))
else range(tp.bottomType, tp.topType)
else range(defn.NothingType, defn.AnyType)
// TODO: can we give a better bound than `topType`?
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Constructors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
// Produce aligned accessors and constructor parameters. We have to adjust
// for any outer parameters, which are last in the sequence of original
// parameter accessors but come first in the constructor parameter list.
val accessors = cls.paramAccessors.filterNot(x => x.isSetter || x.info.resultType.classSymbol == defn.ErasedPhantomClass)
val accessors = cls.paramAccessors.filterNot(x => x.isSetter)
val vparamsWithOuterLast = vparams match {
case vparam :: rest if vparam.name == nme.OUTER => rest ::: vparam :: Nil
case _ => vparams
Expand Down
28 changes: 4 additions & 24 deletions compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import ValueClasses._
import TypeUtils._
import ExplicitOuter._
import core.Mode
import core.PhantomErasure
import reporting.trace

class Erasure extends Phase with DenotTransformer {
Expand Down Expand Up @@ -213,8 +212,6 @@ object Erasure {
val tree1 =
if (tree.tpe isRef defn.NullClass)
adaptToType(tree, underlying)
else if (wasPhantom(underlying))
PhantomErasure.erasedParameterRef
else if (!(tree.tpe <:< tycon)) {
assert(!(tree.tpe.typeSymbol.isPrimitiveValueClass))
val nullTree = Literal(Constant(null))
Expand Down Expand Up @@ -437,16 +434,9 @@ object Erasure {
}
}

if ((origSym eq defn.Phantom_assume) || (origSym.is(Flags.ParamAccessor) && wasPhantom(pt)))
PhantomErasure.erasedAssume
else recur(typed(tree.qualifier, AnySelectionProto))
recur(typed(tree.qualifier, AnySelectionProto))
}

override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): tpd.Tree =
if (tree.symbol eq defn.Phantom_assume) PhantomErasure.erasedAssume
else if (tree.symbol.is(Flags.Param) && wasPhantom(tree.typeOpt)) PhantomErasure.erasedParameterRef
else super.typedIdent(tree, pt)

override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree =
if (tree.symbol == ctx.owner.lexicallyEnclosingClass || tree.symbol.isStaticOwner) promote(tree)
else {
Expand Down Expand Up @@ -507,11 +497,9 @@ object Erasure {
.withType(defn.ArrayOf(defn.ObjectType))
args0 = bunchedArgs :: Nil
}
// Arguments are phantom if an only if the parameters are phantom, guaranteed by the separation of type lattices
val args1 = args0.filterConserve(arg => !wasPhantom(arg.typeOpt))
assert(args1 hasSameLengthAs mt.paramInfos)
val args2 = args1.zipWithConserve(mt.paramInfos)(typedExpr)
untpd.cpy.Apply(tree)(fun1, args2) withType mt.resultType
assert(args0 hasSameLengthAs mt.paramInfos)
val args1 = args0.zipWithConserve(mt.paramInfos)(typedExpr)
untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType
case _ =>
throw new MatchError(i"tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}")
}
Expand Down Expand Up @@ -572,11 +560,6 @@ object Erasure {
rhs1 = untpd.Block(paramDefs, rhs1)
}
vparamss1 = vparamss1.mapConserve(_.filterConserve(!_.symbol.is(Flags.Unused)))
vparamss1 = vparamss1.mapConserve(_.filterConserve(vparam => !wasPhantom(vparam.tpe)))
if (sym.is(Flags.ParamAccessor) && wasPhantom(ddef.tpt.tpe)) {
sym.resetFlag(Flags.ParamAccessor)
rhs1 = PhantomErasure.erasedParameterRef
}
val ddef1 = untpd.cpy.DefDef(ddef)(
tparams = Nil,
vparamss = vparamss1,
Expand Down Expand Up @@ -703,7 +686,4 @@ object Erasure {

def takesBridges(sym: Symbol)(implicit ctx: Context) =
sym.isClass && !sym.is(Flags.Trait | Flags.Package)

private def wasPhantom(tp: Type)(implicit ctx: Context): Boolean =
tp.widenDealias.classSymbol eq defn.ErasedPhantomClass
}
8 changes: 0 additions & 8 deletions compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,6 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase =>
} else ddef
}

override def transformValDef(vdef: tpd.ValDef)(implicit ctx: Context): tpd.Tree = {
if (vdef.tpt.tpe.isPhantom) {
if (vdef.symbol.is(Mutable)) ctx.error("var fields cannot have Phantom types", vdef.pos)
else if (vdef.symbol.hasAnnotation(defn.VolatileAnnot)) ctx.error("Phantom fields cannot be @volatile", vdef.pos)
}
vdef
}

override def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] =
ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisPhase.next)))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,6 @@ object GenericSignatures {
else
jsig(unboxedSeen, toplevel, primitiveOK)
}
else if (tp.isPhantom)
jsig(defn.ErasedPhantomType)
else if (sym.isClass)
classSig
else
Expand Down Expand Up @@ -242,7 +240,7 @@ object GenericSignatures {
// unused method parameters do not make it to the bytecode.
def effectiveParamInfoss(t: Type)(implicit ctx: Context): List[List[Type]] = t match {
case t: MethodType if t.isUnusedMethod => effectiveParamInfoss(t.resType)
case t: MethodType => t.paramInfos.filterNot(_.isPhantom) :: effectiveParamInfoss(t.resType)
case t: MethodType => t.paramInfos :: effectiveParamInfoss(t.resType)
case _ => Nil
}
val params = effectiveParamInfoss(mtpe).flatten
Expand Down
Loading

0 comments on commit 4d41e4f

Please sign in to comment.