Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove scala.Phantom (replaced by unused) #3410

Merged
merged 2 commits into from Mar 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/Compiler.scala
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
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
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
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
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
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
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
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
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
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
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
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
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