diff options
28 files changed, 977 insertions, 589 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 8ea3cd511a..0224f9158e 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -138,6 +138,12 @@ trait Definitions extends reflect.api.StandardDefinitions { // symbols related to packages var emptypackagescope: Scope = null //debug + // TODO - having these as objects means they elude the attempt to + // add synchronization in SynchronizedSymbols. But we should either + // flip on object overrides or find some other accomodation, because + // lazy vals are unnecessarily expensive relative to objects and it + // is very beneficial for a handful of bootstrap symbols to have + // first class identities sealed trait WellKnownSymbol extends Symbol { this initFlags TopLevelCreationFlags } @@ -148,7 +154,7 @@ trait Definitions extends reflect.api.StandardDefinitions { } // This is the package _root_. The actual root cannot be referenced at // the source level, but _root_ is essentially a function => <root>. - final object RootPackage extends ModuleSymbol(NoSymbol, NoPosition, nme.ROOTPKG) with RootSymbol { + final object RootPackage extends PackageSymbol(NoSymbol, NoPosition, nme.ROOTPKG) with RootSymbol { this setInfo NullaryMethodType(RootClass.tpe) RootClass.sourceModule = this @@ -160,7 +166,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // although it is probable that some symbols are created as direct children // of NoSymbol to ensure they will not be stumbled upon. (We should designate // a better encapsulated place for that.) - final object RootClass extends ModuleClassSymbol(NoSymbol, NoPosition, tpnme.ROOT) with RootSymbol { + final object RootClass extends PackageClassSymbol(NoSymbol, NoPosition, tpnme.ROOT) with RootSymbol { this setInfo rootLoader override def isRoot = true @@ -170,10 +176,10 @@ trait Definitions extends reflect.api.StandardDefinitions { override def ownerOfNewSymbols = EmptyPackageClass } // The empty package, which holds all top level types without given packages. - final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + final object EmptyPackage extends PackageSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { override def isEmptyPackage = true } - final object EmptyPackageClass extends ModuleClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + final object EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { override def isEffectiveRoot = true override def isEmptyPackageClass = true } diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala index ce1c8d0908..38f9ec6669 100644 --- a/src/compiler/scala/reflect/internal/Flags.scala +++ b/src/compiler/scala/reflect/internal/Flags.scala @@ -174,6 +174,9 @@ class Flags extends ModifierFlags { final val LateShift = 47L final val AntiShift = 56L + // Flags which sketchily share the same slot + val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL | IMPLCLASS + // ------- late flags (set by a transformer phase) --------------------------------- // // Summary of when these are claimed to be first used. @@ -206,12 +209,24 @@ class Flags extends ModifierFlags { // ------- masks ----------------------------------------------------------------------- + /** To be a little clearer to people who aren't habitual bit twiddlers. + */ + final val AllFlags = -1L + /** These flags can be set when class or module symbol is first created. * They are the only flags to survive a call to resetFlags(). */ final val TopLevelCreationFlags: Long = MODULE | PACKAGE | FINAL | JAVA + // TODO - there's no call to slap four flags onto every package. + final val PackageFlags: Long = TopLevelCreationFlags + + // FINAL not included here due to possibility of object overriding. + // In fact, FINAL should not be attached regardless. We should be able + // to reconstruct whether an object was marked final in source. + final val ModuleFlags: Long = MODULE + /** These modifiers can be set explicitly in source programs. This is * used only as the basis for the default flag mask (which ones to display * when printing a normal message.) @@ -220,15 +235,15 @@ class Flags extends ModifierFlags { PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE | LAZY - /** These modifiers appear in TreePrinter output. */ - final val PrintableFlags: Long = - ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO | - ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC | VBRIDGE | SPECIALIZED | SYNCHRONIZED - /** The two bridge flags */ final val BridgeFlags = BRIDGE | VBRIDGE final val BridgeAndPrivateFlags = BridgeFlags | PRIVATE + /** These modifiers appear in TreePrinter output. */ + final val PrintableFlags: Long = + ExplicitFlags | BridgeFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO | + ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED + /** When a symbol for a field is created, only these flags survive * from Modifiers. Others which may be applied at creation time are: * PRIVATE, LOCAL. @@ -264,7 +279,7 @@ class Flags extends ModifierFlags { final val ConstrFlags: Long = JAVA /** Module flags inherited by their module-class */ - final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC | JAVA | FINAL + final val ModuleToClassFlags: Long = AccessFlags | TopLevelCreationFlags | CASE | SYNTHETIC def getterFlags(fieldFlags: Long): Long = ACCESSOR + ( if ((fieldFlags & MUTABLE) != 0) fieldFlags & ~MUTABLE & ~PRESUPER @@ -407,26 +422,43 @@ class Flags extends ModifierFlags { case _ => "" } - def flagsToString(flags: Long, privateWithin: String): String = { - var f = flags - val pw = - if (privateWithin == "") { - if ((flags & PrivateLocal) == PrivateLocal) { - f &= ~PrivateLocal - "private[this]" - } else if ((flags & ProtectedLocal) == ProtectedLocal) { - f &= ~ProtectedLocal - "protected[this]" - } else { - "" + def accessString(flags: Long, privateWithin: String)= ( + if (privateWithin == "") { + if ((flags & PrivateLocal) == PrivateLocal) "private[this]" + else if ((flags & ProtectedLocal) == ProtectedLocal) "protected[this]" + else if ((flags & PRIVATE) != 0) "private" + else if ((flags & PROTECTED) != 0) "protected" + else "" + } + else if ((flags & PROTECTED) != 0) "protected[" + privateWithin + "]" + else "private[" + privateWithin + "]" + ) + def nonAccessString(flags0: Long)(flagStringFn: Long => String): String = { + val flags = flags0 & ~AccessFlags + // Fast path for common case + if (flags == 0L) "" else { + var sb: StringBuilder = null + var i = 0 + while (i <= MaxBitPosition) { + val mask = rawFlagPickledOrder(i) + if ((flags & mask) != 0L) { + val s = flagStringFn(mask) + if (s.length > 0) { + if (sb eq null) sb = new StringBuilder append s + else if (sb.length == 0) sb append s + else sb append " " append s + } } - } else if ((f & PROTECTED) != 0L) { - f &= ~PROTECTED - "protected[" + privateWithin + "]" - } else { - "private[" + privateWithin + "]" + i += 1 } - List(flagsToString(f), pw) filterNot (_ == "") mkString " " + if (sb eq null) "" else sb.toString + } + } + + def flagsToString(flags: Long, privateWithin: String): String = { + val access = accessString(flags, privateWithin) + val nonAccess = flagsToString(flags & ~AccessFlags) + List(nonAccess, access) filterNot (_ == "") mkString " " } // List of the raw flags, in pickled order diff --git a/src/compiler/scala/reflect/internal/HasFlags.scala b/src/compiler/scala/reflect/internal/HasFlags.scala index 8affd66cd5..2f574b6bfa 100644 --- a/src/compiler/scala/reflect/internal/HasFlags.scala +++ b/src/compiler/scala/reflect/internal/HasFlags.scala @@ -1,76 +1,6 @@ package scala.reflect package internal -/** ISSUE #1: Flag names vs. Test method names - * - * The following methods from Symbol have a name of - * the form isFoo where FOO is the name of a flag, but where the method - * body tests for more than whether the flag is set. - * - * There are two possibilities with such methods. Either the extra - * tests are strictly to partition among overloaded flags (which is - * the case we can live with in the short term, if each such flag's - * partitioning assumptions are documented) or they aren't. - * - * The second case implies that "x hasFlag FOO" and "x.isFoo" have - * different semantics, and this we can't live with, because even if - * we're smart enough to avoid being tripped up by that, the next guy isn't. - * - * No extreme measures necessary, only renaming isFoo to something - * which hews more closely to its implementation. (Or renaming the flag.) - * - // Defined in the compiler Symbol - // - final def isLabel = isMethod && !hasAccessorFlag && hasFlag(LABEL) - final def isLocal: Boolean = owner.isTerm - final def isModuleVar: Boolean = isVariable && hasFlag(MODULEVAR) - final def isStable = - isTerm && - !hasTraitFlag && - (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) && - !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass)) - final def isStatic: Boolean = - hasFlag(STATIC) || isRoot || owner.isStaticOwner - override final def isTrait: Boolean = - isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE) - - // Defined in the library Symbol - // - def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes. - final def isContravariant = isType && hasFlag(CONTRAVARIANT) - final def isCovariant = isType && hasFlag(COVARIANT) - final def isMethod = isTerm && hasFlag(METHOD) - final def isModule = isTerm && hasFlag(MODULE) - final def isPackage = isModule && hasFlag(PACKAGE) - * - */ - -/** ISSUE #2: Implicit flag relationships must be made explicit. - * - * For instance, every time the MODULE flag is set, the FINAL flag is - * set along with it: - * - .setFlag(FINAL | MODULE | PACKAGE | JAVA) - .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader) - new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) - new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) - val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) - setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL) - sourceModule.flags = MODULE | FINAL - - * However the same is not true of when the MODULE flag is cleared: - - sym.resetFlag(MODULE) - .setFlag(sym.flags | STABLE).resetFlag(MODULE) - sym.resetFlag(MODULE | FINAL | CASE) - - * It's not relevant whether this example poses any issues: we must - * not tolerate these uncertainties. If the flags are to move together - * then both setting and clearing have to be encapsulated. If there - * is a useful and used distinction between the various permutations - * of on and off, then it must be documented. It's the only way! - */ - import Flags._ /** Common code utilized by Modifiers (which carry the flags associated @@ -165,26 +95,20 @@ trait HasFlags { // which must have been a bug. def isPublic = hasNoFlags(PRIVATE | PROTECTED) && !hasAccessBoundary - // Renamed the Modifiers impl from isArgument. - def isParameter = hasFlag(PARAM) - // Removed isClass qualification since the flag isn't overloaded and // sym.isClass is enforced in Namers#validate. def isSealed = hasFlag(SEALED) // Removed !isClass qualification since the flag isn't overloaded. - def isDeferred = hasFlag(DEFERRED ) + def isDeferred = hasFlag(DEFERRED) // Dropped isTerm condition because flag isn't overloaded. def isAbstractOverride = hasFlag(ABSOVERRIDE) def isAnyOverride = hasFlag(OVERRIDE | ABSOVERRIDE) - def isDefaultInit = hasFlag(DEFAULTINIT) // Disambiguating: DEFAULTPARAM, TRAIT def hasDefault = hasAllFlags(DEFAULTPARAM | PARAM) def isTrait = hasFlag(TRAIT) && !hasFlag(PARAM) - def hasTraitFlag = hasFlag(TRAIT) - def hasDefaultFlag = hasFlag(DEFAULTPARAM) // Straightforwardly named accessors already being used differently. // These names are most likely temporary. @@ -193,16 +117,9 @@ trait HasFlags { def hasLocalFlag = hasFlag(LOCAL) def hasModuleFlag = hasFlag(MODULE) def hasPackageFlag = hasFlag(PACKAGE) - def hasPreSuperFlag = hasFlag(PRESUPER) def hasStableFlag = hasFlag(STABLE) def hasStaticFlag = hasFlag(STATIC) - // Disambiguating: BYNAMEPARAM, CAPTURED, COVARIANT. - def isByNameParam = hasAllFlags(BYNAMEPARAM | PARAM) - // Nope, these aren't going to fly: - // def isCapturedVariable = hasAllFlags(CAPTURED | MUTABLE) - // def isCovariant = hasFlag(COVARIANT) && hasNoFlags(PARAM | MUTABLE) - // Disambiguating: LABEL, CONTRAVARIANT, INCONSTRUCTOR def isLabel = hasAllFlags(LABEL | METHOD) && !hasAccessorFlag // Cannot effectively disambiguate the others at this level. @@ -212,23 +129,13 @@ trait HasFlags { // Name def isJavaDefined = hasFlag(JAVA) - // Keeping some potentially ambiguous names around so as not to break - // the rest of the world + // Backward compat section + @deprecated( "Use isTrait", "2.10.0") + def hasTraitFlag = hasFlag(TRAIT) + @deprecated("Use hasDefault", "2.10.0") + def hasDefaultFlag = hasFlag(DEFAULTPARAM) @deprecated("", "2.9.0") def isAbstract = hasFlag(ABSTRACT) - // Problematic: - // ABSTRACT and DEFERRED too easy to confuse, and - // ABSTRACT + OVERRIDE ==> ABSOVERRIDE adds to it. - // - // final def isAbstractClass = isClass && hasFlag(ABSTRACT) - // def isAbstractType = false // to be overridden - - // Question: - // Which name? All other flags are isFlag so it's probably a mistake to - // vary from that, but isAccessor does sound like it includes the other - // *ACCESSOR flags. Perhaps something like isSimpleAccessor. - // - // def isAccessor = hasFlag(ACCESSOR ) - // final def isGetterOrSetter = hasAccessorFlag + @deprecated("Use isValueParameter or isTypeParameter", "2.10.0") + def isParameter = hasFlag(PARAM) } - diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 04381937d1..5dcff804a8 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -63,7 +63,7 @@ trait Importers { self: SymbolTable => } myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags) case x: from.ModuleClassSymbol => - val mysym = myowner.newModuleClassSymbol(myname.toTypeName, mypos, myflags) + val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags) symMap(x) = mysym mysym.sourceModule = importSymbol(x.sourceModule) mysym @@ -109,14 +109,18 @@ trait Importers { self: SymbolTable => val owner = sym.owner var scope = if (owner.isClass && !owner.isRefinementClass) owner.info else from.NoType var existing = scope.decl(name) - if (sym.isPackageClass || sym.isModuleClass) existing = existing.moduleClass + if (sym.isModuleClass) + existing = existing.moduleClass + if (!existing.exists) scope = from.NoType val myname = importName(name) val myowner = importSymbol(owner) val myscope = if (scope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType var myexisting = if (myscope != NoType) myowner.info.decl(myname) else NoSymbol // cannot load myexisting in general case, because it creates cycles for methods - if (sym.isPackageClass || sym.isModuleClass) myexisting = importSymbol(sym.sourceModule).moduleClass + if (sym.isModuleClass) + myexisting = importSymbol(sym.sourceModule).moduleClass + if (!sym.isOverloaded && myexisting.isOverloaded) { myexisting = if (sym.isMethod) { diff --git a/src/compiler/scala/reflect/internal/SymbolCreations.scala b/src/compiler/scala/reflect/internal/SymbolCreations.scala new file mode 100644 index 0000000000..62fee9d7f3 --- /dev/null +++ b/src/compiler/scala/reflect/internal/SymbolCreations.scala @@ -0,0 +1,106 @@ + /* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.reflect +package internal + +import scala.collection.{ mutable, immutable } +import scala.collection.mutable.ListBuffer +import util.Statistics._ +import Flags._ +import api.Modifier +import scala.tools.util.StringOps.{ ojoin } + +trait SymbolCreations { + self: SymbolTable => + + import definitions._ + + /** Symbol creation interface, possibly better moved somewhere else. + * It'd be nice if we had virtual classes, but since we + * don't: these methods insulate the direct instantiation of the symbols + * (which may be overridden, e.g. in SynchronizedSymbols) from the + * enforcement of preconditions and choice of symbol constructor based + * on flags, which are (or should be) final so they can be reasoned about + * without lots of surprises. + */ + trait SymbolCreatorInterface { + // Fallbacks; more precise creators should normally be called. + protected def createTypeSymbol(name: TypeName, pos: Position, newFlags: Long): TypeSymbol + protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol + + // I believe all but rogue TypeSymbols are one of: ClassSymbol, AbstractTypeSymbol, AliasTypeSymbol, or TypeSkolem. + protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol + protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol + protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem + protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol + + // More specific ClassSymbols. + // TODO - AnonymousClassSymbol. + // TODO maybe - PackageObjects, but that one cost me a lot of time when I tried it before + // because it broke reification some way I couldn't see. + protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol + protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol + protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol + + // Distinguished term categories include methods, modules, packages, package objects, + // value parameters, and values (including vals, vars, and lazy vals.) + protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol + protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol + protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol + + // TODO + // protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol + // protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol + } + + trait SymbolCreator extends SymbolCreatorInterface { + self: Symbol => + + /*** Predictable symbol creation. + * + * newTermSymbol, newClassSymbol, and newNonClassSymbol all create symbols based + * only on the flags (for reconstruction after reification.) It would be nice to + * combine the last two into newTypeSymbol, but this requires some flag which allows us + * to distinguish classes and type aliases, which as yet does not exist. + * + * The fundamental flags used to determine which Symbol subclass to instantiate are: + * METHOD, PACKAGE, MODULE, PARAM, DEFERRED. + */ + final def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = { + if ((newFlags & METHOD) != 0) + createMethodSymbol(name, pos, newFlags) + else if ((newFlags & PACKAGE) != 0) + createPackageSymbol(name, pos, newFlags | PackageFlags) + else if ((newFlags & MODULE) != 0) + createModuleSymbol(name, pos, newFlags) + else if ((newFlags & PARAM) != 0) + createValueParameterSymbol(name, pos, newFlags) + else + createValueMemberSymbol(name, pos, newFlags) + } + + final def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = { + if (name == tpnme.REFINE_CLASS_NAME) + createRefinementClassSymbol(pos, newFlags) + else if ((newFlags & PACKAGE) != 0) + createPackageClassSymbol(name, pos, newFlags | PackageFlags) + else if ((newFlags & MODULE) != 0) + createModuleClassSymbol(name, pos, newFlags) + else + createClassSymbol(name, pos, newFlags) + } + + final def newNonClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = { + if ((newFlags & DEFERRED) != 0) + createAbstractTypeSymbol(name, pos, newFlags) + else + createAliasTypeSymbol(name, pos, newFlags) + } + + def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = + newNonClassSymbol(name, pos, newFlags) + } +} diff --git a/src/compiler/scala/reflect/internal/SymbolFlags.scala b/src/compiler/scala/reflect/internal/SymbolFlags.scala new file mode 100644 index 0000000000..0b49ee2505 --- /dev/null +++ b/src/compiler/scala/reflect/internal/SymbolFlags.scala @@ -0,0 +1,237 @@ + /* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.reflect +package internal + +import scala.collection.{ mutable, immutable } +import scala.collection.mutable.ListBuffer +import util.Statistics._ +import Flags._ +import api.Modifier +import scala.tools.util.StringOps.{ ojoin } + +trait SymbolFlags { + self: SymbolTable => + + import definitions._ + + /** Not mixed in under normal conditions; a powerful debugging aid. + */ + trait FlagVerifier extends SymbolFlagLogic { + this: Symbol => + + private def assert0(cond: Boolean, message: => Any) { + if (!cond) { + Console.err.println("[flag verification failure]\n%s\n%s\n".format(atPhaseStackMessage, message)) + (new Throwable).getStackTrace.take(13).drop(3).foreach(println) + println("") + } + } + + protected def verifyChange(isAdd: Boolean, mask: Long, before: Long) { + val after = if (isAdd) before | mask else before & ~mask + val added = after & ~before + val removed = before & ~after + val ignored = mask & ~added & ~removed + val error = ( + (added & OverloadedFlagsMask) != 0 || (removed & OverloadedFlagsMask) != 0 + // || (ignored != 0) + ) + val addString = if (added == 0) "" else "+(" + flagsToString(added) + ")" + val removeString = if (removed == 0) "" else "-(" + flagsToString(removed) + ")" + val changeString = if (added == 0 && removed == 0) "no change" else addString + " " + removeString + + if (error) { + val templ = ( + """| symbol: %s %s in %s + | call: %s(%s) + | flags: %s + | result: %s""".stripMargin + ) + + assert0(false, templ.format( + shortSymbolClass, + name.decode, + owner, + if (isAdd) "+" else "-", + flagsToString(mask), + flagsToString(before), + changeString + )) + } + } + + protected def verifyFlags(what: String) { + assert0(this hasAllFlags alwaysHasFlags, symbolCreationString + "\n always=%s, what=%s\n".format(flagsToString(alwaysHasFlags), what)) + if (this hasFlag neverHasFlags) { + val hasRaw = (rawflags & neverHasFlags) != 0 + assert0(!hasRaw, symbolCreationString + "\n never=%s, what=%s".format(flagsToString(neverHasFlags), what)) + } + } + override def initFlags(mask: Long): this.type = { + super.initFlags(mask) + verifyFlags("initFlags(" + flagsToString(mask) + ")") + this + } + override def setFlag(mask: Long): this.type = { + verifyChange(true, mask, rawflags) + super.setFlag(mask) + verifyFlags("setFlag(" + flagsToString(mask) + ")") + this + } + override def resetFlag(mask: Long): this.type = { + verifyChange(false, mask, rawflags) + super.resetFlag(mask) + verifyFlags("resetFlag(" + flagsToString(mask) + ")") + this + } + override def flags_=(fs: Long) { + if ((fs & ~rawflags) != 0) + verifyChange(true, fs & ~rawflags, rawflags) + if ((rawflags & ~fs) != 0) + verifyChange(false, rawflags & ~fs, rawflags) + + super.flags_=(fs) + verifyFlags("flags_=(" + flagsToString(fs) + ")") + } + } + + /** A distinguishing flag is one which the mixing class must always + * have, and which no other symbol class is allowed to have. + */ + trait DistinguishingFlag extends SymbolFlagLogic { + this: Symbol => + + def distinguishingFlag: Long + override protected def alwaysHasFlags = super.alwaysHasFlags | distinguishingFlag + override protected def neverHasFlags = super.neverHasFlags & ~distinguishingFlag + } + + trait SymbolFlagLogic { + this: Symbol => + + protected def alwaysHasFlags: Long = 0L + protected def neverHasFlags: Long = METHOD | MODULE + + def flagStringFn(flag: Long): String = { + val res = flag match { + // "<bynameparam/captured/covariant>" + case BYNAMEPARAM => + if (this.isValueParameter) "<bynameparam>" + else if (this.isTypeParameter) "<covariant>" + else "<captured>" + // "<contravariant/inconstructor/label>" + case CONTRAVARIANT => + if (this.isLabel) "<label>" + else if (this.isTypeParameter) "<contravariant>" + else "<inconstructor>" + // "<defaultparam/trait>" + case DEFAULTPARAM => + if (this.isTerm && (this hasFlag PARAM)) "<defaultparam>" + else "<trait>" + // "<existential/mixedin>" + case EXISTENTIAL => + if (this.isType) "<existential>" + else "<mixedin>" + // "<implclass/presuper>" + case IMPLCLASS => + if (this.isClass) "<implclass>" + else "<presuper>" + case _ => "" + } + if (res == "") Flags.flagToString(flag) + else res + ":overloaded-flag" + } + + private def calculateFlagString(basis: Long): String = { + val nonAccess = nonAccessString(basis)(flagStringFn) + val access = Flags.accessString(basis, pwString) + + ojoin(nonAccess, access) + } + + def flagString(mask: Long): String = calculateFlagString(flags & mask) + def flagString: String = flagString(defaultFlagMask) + def rawFlagString(mask: Long): String = calculateFlagString(rawflags & mask) + def rawFlagString: String = rawFlagString(defaultFlagMask) + def flaggedString(mask: Long): String = flagString(mask) + def flaggedString: String = flaggedString(defaultFlagMask) + + def accessString = calculateFlagString(flags & AccessFlags) + def debugFlagString = flaggedString(AllFlags) + def defaultFlagString = flaggedString(defaultFlagMask) + + def hasFlagsToString(mask: Long) = flagString(mask) + + /** String representation of symbol's variance */ + def varianceString: String = + if (variance == 1) "+" + else if (variance == -1) "-" + else "" + + def defaultFlagMask = + if (settings.debug.value && !isAbstractType) AllFlags + else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE + else ExplicitFlags + + // make the error message more googlable + def flagsExplanationString = + if (isGADTSkolem) " (this is a GADT skolem)" + else "" + + private def pwString = if (hasAccessBoundary) privateWithin.toString else "" + private var _rawflags: FlagsType = 0L + protected def rawflags_=(x: FlagsType) { _rawflags = x } + def rawflags = _rawflags + + final def flags: Long = { + val fs = rawflags & phase.flagMask + (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) + } + def flags_=(fs: Long) = rawflags = fs + + /** Set the symbol's flags to the given value, asserting + * that the previous value was 0. + */ + def initFlags(mask: Long): this.type = { + assert(rawflags == 0L, symbolCreationString) + rawflags = mask + this + } + def reinitFlags(mask: Long): this.type = { + rawflags = mask + this + } + def setFlag(mask: Long): this.type = { rawflags |= mask ; this } + def resetFlag(mask: Long): this.type = { rawflags &= ~mask ; this } + def resetFlags() { rawflags &= (TopLevelCreationFlags | alwaysHasFlags) } + + def getFlag(mask: Long): Long + def hasFlag(mask: Long): Boolean + def hasAllFlags(mask: Long): Boolean + + /** If the given flag is set on this symbol, also set the corresponding + * notFLAG. For instance if flag is PRIVATE, the notPRIVATE flag will + * be set if PRIVATE is currently set. + */ + final def setNotFlag(flag: Int) = if (hasFlag(flag)) setFlag((flag: @annotation.switch) match { + case PRIVATE => notPRIVATE + case PROTECTED => notPROTECTED + case OVERRIDE => notOVERRIDE + case _ => abort("setNotFlag on invalid flag: " + flag) + }) + + protected def shortSymbolClass = getClass.getName.split('.').last.stripPrefix("Symbols$") + def symbolCreationString: String = ( + "%s%25s | %-40s | %s".format( + if (settings.uniqid.value) "%06d | ".format(id) else "", + shortSymbolClass, + name.decode + " in " + owner, + rawFlagString + ) + ) + } +} diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index 256c1a6ced..daaf0dff26 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -13,7 +13,9 @@ import scala.tools.nsc.util.WeakHashSet abstract class SymbolTable extends api.Universe with Collections with Names + with SymbolCreations with Symbols + with SymbolFlags with Types with Kinds with ExistentialsAndSkolems @@ -62,6 +64,8 @@ abstract class SymbolTable extends api.Universe result } + /** Dump each symbol to stdout after shutdown. + */ final val traceSymbolActivity = sys.props contains "scalac.debug.syms" object traceSymbols extends { val global: SymbolTable.this.type = SymbolTable.this @@ -98,6 +102,11 @@ abstract class SymbolTable extends api.Universe final def atPhaseStack: List[Phase] = phStack final def phase: Phase = ph + def atPhaseStackMessage = atPhaseStack match { + case Nil => "" + case ps => ps.reverseMap("->" + _).mkString("(", " ", ")") + } + final def phase_=(p: Phase) { //System.out.println("setting phase to " + p) assert((p ne null) && p != NoPhase, p) diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 5c43047046..cfab069588 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -55,11 +55,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ val originalOwner = perRunCaches.newMap[Symbol, Symbol]() - abstract class AbsSymbolImpl extends AbsSymbol { this: Symbol => - def newNestedSymbol(name: Name, pos: Position, newFlags: Long) = name match { + abstract class AbsSymbolImpl extends AbsSymbol { + this: Symbol => + + def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match { case n: TermName => newTermSymbol(n, pos, newFlags) - case n: TypeName => newTypeSymbol(n, pos, newFlags) + case n: TypeName => if (isClass) newClassSymbol(n, pos, newFlags) else newNonClassSymbol(n, pos, newFlags) } + def enclosingClass: Symbol = enclClass def enclosingMethod: Symbol = enclMethod def thisPrefix: Type = thisType @@ -79,6 +82,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) extends AbsSymbolImpl with HasFlags + with SymbolFlagLogic + with SymbolCreator + // with FlagVerifier with Annotatable[Symbol] { type FlagsType = Long @@ -87,13 +93,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api private[this] var _rawname = initName - private[this] var _rawflags = 0L def rawowner = _rawowner def rawname = _rawname - def rawflags = _rawflags - - protected def rawflags_=(x: FlagsType) { _rawflags = x } private var rawpos = initPos @@ -135,7 +137,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newLocalDummy(pos: Position) = newTermSymbol(nme.localDummyName(this), pos) setInfo NoType final def newMethod(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol = - newMethodSymbol(name, pos, METHOD | newFlags) + createMethodSymbol(name, pos, METHOD | newFlags) final def newLabel(name: TermName, pos: Position = NoPosition): MethodSymbol = newMethod(name, pos, LABEL) @@ -146,73 +148,39 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Static constructor with info set. */ def newStaticConstructor(pos: Position) = newConstructor(pos, STATIC) setInfo UnitClass.tpe + /** Instance constructor with info set. */ def newClassConstructor(pos: Position) = newConstructor(pos) setInfo MethodType(Nil, this.tpe) - // Top-level objects can be automatically marked final, but others - // must be explicitly marked final if overridable objects are enabled. - private def ModuleFlags = ( - if (isPackage || !settings.overrideObjects.value) MODULE | FINAL - else MODULE - ) def newLinkedModule(clazz: Symbol, newFlags: Long = 0L): ModuleSymbol = { - val m = newModuleSymbol(clazz.name.toTermName, clazz.pos, ModuleFlags | newFlags) + val m = newModuleSymbol(clazz.name.toTermName, clazz.pos, MODULE | newFlags) connectModuleToClass(m, clazz.asInstanceOf[ClassSymbol]) } final def newModule(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = { - val m = newModuleSymbol(name, pos, newFlags | ModuleFlags) - val clazz = newModuleClassSymbol(name.toTypeName, pos, (m getFlag ModuleToClassFlags) | MODULE) + val m = newModuleSymbol(name, pos, newFlags | MODULE) + val clazz = newModuleClass(name.toTypeName, pos, m getFlag ModuleToClassFlags) connectModuleToClass(m, clazz) } final def newPackage(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = { assert(name == nme.ROOT || isPackageClass, this) - newModule(name, pos, JAVA | PACKAGE | newFlags) + newModule(name, pos, PackageFlags | newFlags) } + final def newThisSym(pos: Position) = newTermSymbol(nme.this_, pos, SYNTHETIC) final def newImport(pos: Position) = newTermSymbol(nme.IMPORT, pos) - /** Direct symbol factories. - * For internal use; these are unlikely to be what you want. - */ - def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = - new TermSymbol(this, pos, name) initFlags newFlags + final def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = + newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol] - def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol = - new AbstractTypeSymbol(this, pos, name) initFlags newFlags + final def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = + newClassSymbol(name, pos, newFlags).asInstanceOf[ModuleClassSymbol] - def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol = - new AliasTypeSymbol(this, pos, name) initFlags newFlags - - def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = - new ModuleSymbol(this, pos, name) initFlags newFlags - - def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol = - new MethodSymbol(this, pos, name) initFlags newFlags - - def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = - new ClassSymbol(this, pos, name) initFlags newFlags - - def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = - new ModuleClassSymbol(this, pos, name) initFlags newFlags - - /** Derive whether it is an abstract type from the flags; after creation - * the DEFERRED flag will be ignored. - */ - def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = - if ((newFlags & DEFERRED) == 0L) - newAliasTypeSymbol(name, pos, newFlags) - else - newAbstractTypeSymbol(name, pos, newFlags) - - def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem = - if ((newFlags & DEFERRED) == 0L) - new TypeSkolem(this, pos, name, origin) initFlags newFlags - else - new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin initFlags newFlags + final def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem = + createTypeSkolemSymbol(name, origin, pos, newFlags) /** @param pre type relative to which alternatives are seen. * for instance: @@ -243,18 +211,23 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Symbol of a type definition type T = ... */ final def newAliasType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol = - newAliasTypeSymbol(name, pos, newFlags) + createAliasTypeSymbol(name, pos, newFlags) /** Symbol of an abstract type type T >: ... <: ... */ final def newAbstractType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol = - newAbstractTypeSymbol(name, pos, DEFERRED | newFlags) + createAbstractTypeSymbol(name, pos, DEFERRED | newFlags) /** Symbol of a type parameter */ final def newTypeParameter(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) = newAbstractType(name, pos, PARAM | newFlags) + /** Symbol of an existential type T forSome { ... } + */ + final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol = + newAbstractType(name, pos, EXISTENTIAL | newFlags) + /** Synthetic value parameters when parameter symbols are not available */ final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[Symbol]] = { @@ -280,10 +253,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def newGADTSkolem(name: TypeName, origin: Symbol, info: Type): TypeSkolem = newTypeSkolemSymbol(name, origin, origin.pos, origin.flags & ~(EXISTENTIAL | PARAM) | CASEACCESSOR | SYNTHETIC) setInfo info - - final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol = - newAbstractType(name, pos, EXISTENTIAL | newFlags) - final def freshExistential(suffix: String): Symbol = newExistential(freshExistentialName(suffix), pos) @@ -318,8 +287,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newErrorClass(name: TypeName) = newClassWithInfo(name, Nil, new ErrorScope(this), pos, SYNTHETIC | IS_ERROR) - final def newModuleClass(name: TypeName, pos: Position = NoPosition) = - newModuleClassSymbol(name, pos) + final def newModuleClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) = + newModuleClassSymbol(name, pos, newFlags | MODULE) final def newAnonymousClass(pos: Position) = newClassSymbol(tpnme.ANON_CLASS_NAME, pos) @@ -333,8 +302,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Refinement types P { val x: String; type T <: Number } * also have symbols, they are refinementClasses */ - final def newRefinementClass(pos: Position) = - newClass(tpnme.REFINE_CLASS_NAME, pos) + final def newRefinementClass(pos: Position) = createRefinementClassSymbol(pos, 0L) /** Create a new getter for current symbol (which must be a field) */ @@ -410,7 +378,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => if ((rawflags & LOCKED) != 0L) { // activeLocks -= 1 // lockedSyms -= this - _rawflags = rawflags & ~LOCKED + rawflags &= ~LOCKED if (settings.Yrecursion.value != 0) recursionTable -= this } @@ -418,42 +386,84 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ----- tests ---------------------------------------------------------------------- - def isTerm = false // to be overridden - def isType = false // to be overridden - def isClass = false // to be overridden - def isBottomClass = false // to be overridden - def isAliasType = false // to be overridden - def isAbstractType = false // to be overridden - private[scala] def isSkolem = false // to be overridden - - /** Is this symbol a type but not a class? */ - def isNonClassType = false // to be overridden - - override final def isTrait = isClass && hasFlag(TRAIT) - final def isAbstractClass = isClass && hasFlag(ABSTRACT) - final def isBridge = hasFlag(BRIDGE) - final def isContravariant = isType && hasFlag(CONTRAVARIANT) - final def isConcreteClass = isClass && !hasFlag(ABSTRACT | TRAIT) - final def isCovariant = isType && hasFlag(COVARIANT) - final def isEarlyInitialized = isTerm && hasFlag(PRESUPER) - final def isExistentiallyBound = isType && hasFlag(EXISTENTIAL) - final def isImplClass = isClass && hasFlag(IMPLCLASS) - final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol - final def isMethod = isTerm && hasFlag(METHOD) - final def isModule = isTerm && hasFlag(MODULE) - final def isModuleClass = isClass && hasFlag(MODULE) - final def isNumericValueClass = definitions.isNumericValueClass(this) - final def isOverloaded = hasFlag(OVERLOADED) - final def isOverridableMember = !(isClass || isEffectivelyFinal) && owner.isClass - final def isRefinementClass = isClass && name == tpnme.REFINE_CLASS_NAME - final def isSourceMethod = isMethod && !hasFlag(STABLE) // exclude all accessors!!! - final def isTypeParameter = isType && isParameter && !isSkolem - final def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this) - final def isVarargsMethod = isMethod && hasFlag(VARARGS) - - /** Package tests */ - final def isPackage = isModule && hasFlag(PACKAGE) - final def isPackageClass = isClass && hasFlag(PACKAGE) + /** All symbols are one of three categories: TermSymbol, TypeSymbol, or NoSymbol. + * There is only one NoSymbol. + */ + def isTerm = false + def isType = false + + /** TypeSymbols fall into four named direct subclasses: + * - ClassSymbol + * - AliasTypeSymbol + * - AbstractTypeSymbol + * - TypeSkolem + */ + def isClass = false + def isAliasType = false + def isAbstractType = false + def isSkolem = false + + /** A Type, but not a Class. */ + def isNonClassType = false + + /** The bottom classes are Nothing and Null, found in Definitions. */ + def isBottomClass = false + + /** These are all tests for varieties of ClassSymbol, which has these subclasses: + * - ModuleClassSymbol + * - RefinementClassSymbol + * - PackageClassSymbol (extends ModuleClassSymbol) + */ + def isAbstractClass = false + def isAnonOrRefinementClass = false + def isAnonymousClass = false + def isConcreteClass = false + def isImplClass = false // the implementation class of a trait + def isModuleClass = false + def isNumericValueClass = false + def isPrimitiveValueClass = false + def isRefinementClass = false + override def isTrait = false + + /** Qualities of Types, always false for TermSymbols. + */ + def isContravariant = false + def isCovariant = false + def isExistentialSkolem = false + def isExistentiallyBound = false + def isExistentialQuantified = false + def isGADTSkolem = false + def isTypeParameter = false + def isTypeParameterOrSkolem = false + def isTypeSkolem = false + + /** Qualities of Terms, always false for TypeSymbols. + */ + override def hasDefault = false + def isBridge = false + def isEarlyInitialized = false + def isModule = false + def isOverloaded = false + def isValueParameter = false + + /** Qualities of MethodSymbols, always false for TypeSymbols + * and other TermSymbols. + */ + def isCaseAccessorMethod = false + def isLiftedMethod = false + def isMacro = false + def isMethod = false + def isSourceMethod = false + def isVarargsMethod = false + + /** Package/package object tests */ + def isPackage = false + def isPackageClass = false + def isPackageObject = false + def isPackageObjectClass = false + + def isPackageObjectOrClass = isPackageObject || isPackageObjectClass + def isModuleOrModuleClass = isModule || isModuleClass /** Overridden in custom objects in Definitions */ def isRoot = false @@ -466,22 +476,30 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def isEffectiveRoot = false - /** For RootClass, EmptyPackageClass. For all other symbols, itself. + /** For RootClass, this is EmptyPackageClass. For all other symbols, + * the symbol itself. */ def ownerOfNewSymbols = this + final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol + final def isOverridableMember = !(isClass || isEffectivelyFinal) && owner.isClass + /** Does this symbol denote a wrapper created by the repl? */ final def isInterpreterWrapper = ( - (isModule || isModuleClass) + (this hasFlag MODULE) && owner.isPackageClass && nme.isReplWrapperName(name) ) + @inline final override def getFlag(mask: Long): Long = flags & mask + /** Does symbol have ANY flag in `mask` set? */ + @inline final override def hasFlag(mask: Long): Boolean = (flags & mask) != 0 + /** Does symbol have ALL the flags in `mask` set? */ + @inline final override def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask /** Term symbols with the exception of static parts of Java classes and packages. */ - final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA)) - - final def isVariable = isTerm && isMutable && !isMethod + final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA)) + final def isVariable = isTerm && isMutable && !isMethod // interesting only for lambda lift. Captured variables are accessed from inner lambdas. final def isCapturedVariable = isVariable && hasFlag(CAPTURED) @@ -493,9 +511,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def hasGetter = isTerm && nme.isLocalName(name) - final def isValueParameter = isTerm && hasFlag(PARAM) - final def isLocalDummy = isTerm && nme.isLocalDummyName(name) final def isInitializedToDefault = !isType && hasAllFlags(DEFAULTINIT | ACCESSOR) + final def isLocalDummy = isTerm && nme.isLocalDummyName(name) final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR) final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR) final def isConstructor = isTerm && nme.isConstructorName(name) @@ -503,17 +520,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isThisSym = isTerm && owner.thisSym == this final def isError = hasFlag(IS_ERROR) final def isErroneous = isError || isInitialized && tpe.isErroneous - final def isTypeParameterOrSkolem = isType && hasFlag(PARAM) - final def isHigherOrderTypeParameter = (this ne NoSymbol) && owner.isTypeParameterOrSkolem - final def isTypeSkolem = isSkolem && hasFlag(PARAM) - // a type symbol bound by an existential type, for instance the T in - // List[T] forSome { type T } - final def isExistentialSkolem = isExistentiallyBound && isSkolem - final def isExistentialQuantified = isExistentiallyBound && !isSkolem - final def isGADTSkolem = isSkolem && hasFlag(CASEACCESSOR | SYNTHETIC) + + def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor - final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) + def isClassLocalToConstructor = false final def isDerivedValueClass = isClass && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass @@ -521,29 +532,27 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isMethodWithExtension = isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) - final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME) - final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) - final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass - - // A package object or its module class - final def isPackageObjectOrClass = (this ne NoSymbol) && owner.isPackageClass && (name == nme.PACKAGE || name == tpnme.PACKAGE) - final def isPackageObject = (this ne NoSymbol) && owner.isPackageClass && name == nme.PACKAGE - final def isPackageObjectClass = (this ne NoSymbol) && owner.isPackageClass && name == tpnme.PACKAGE - + final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) final def isDefinedInPackage = effectiveOwner.isPackageClass - final def isJavaInterface = isJavaDefined && isTrait - final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass + final def isJavaInterface = isJavaDefined && isTrait + final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass + + /** change name by appending $$<fully-qualified-name-of-class `base`> + * Do the same for any accessed symbols or setters/getters. + * Implementation in TermSymbol. + */ + def expandName(base: Symbol) { } // In java.lang, Predef, or scala package/package object def isInDefaultNamespace = UnqualifiedOwners(effectiveOwner) /** The owner, skipping package objects. */ - def effectiveOwner = if (owner.isPackageObjectClass) owner.skipPackageObject else owner + def effectiveOwner = owner.skipPackageObject /** If this is a package object or its implementing class, its owner: otherwise this. */ - final def skipPackageObject: Symbol = if (isPackageObjectOrClass) owner else this + def skipPackageObject: Symbol = if (this.isPackageObjectOrClass) owner else this /** If this is a constructor, its owner: otherwise this. */ @@ -622,15 +631,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => // def isVirtualClass = hasFlag(DEFERRED) && isClass // def isVirtualTrait = hasFlag(DEFERRED) && isTrait - def isLiftedMethod = isMethod && hasFlag(LIFTED) + // def isLiftedMethod = hasAllFlags(METHOD | LIFTED) def isCaseClass = isClass && isCase - // unfortunately having the CASEACCESSOR flag does not actually mean you - // are a case accessor (you can also be a field.) - def isCaseAccessorMethod = isMethod && isCaseAccessor - - def isMacro = isMethod && hasFlag(MACRO) - /** Does this symbol denote the primary constructor of its enclosing class? */ final def isPrimaryConstructor = isConstructor && owner.primaryConstructor == this @@ -675,10 +678,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isStaticOwner: Boolean = isPackageClass || isModuleClass && isStatic + def isTopLevelModule = hasFlag(MODULE) && owner.isPackageClass + /** Is this symbol effectively final? I.e, it cannot be overridden */ final def isEffectivelyFinal: Boolean = ( - isFinal - || hasModuleFlag && !settings.overrideObjects.value + (this hasFlag FINAL | PACKAGE) + || isModuleOrModuleClass && (owner.isPackageClass || !settings.overrideObjects.value) || isTerm && ( isPrivate || isLocal @@ -693,7 +698,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isConstant: Boolean = isStable && isConstantType(tpe.resultType) /** Is this class nested in another class or module (not a package)? */ - def isNestedClass = isClass && !owner.isPackageClass + def isNestedClass = false /** Is this class locally defined? * A class is local, if @@ -701,9 +706,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => * - its owner is a value * - it is defined within a local class */ - final def isLocalClass: Boolean = - isClass && (isAnonOrRefinementClass || isLocal || - !owner.isPackageClass && owner.isLocalClass) + def isLocalClass = false + + def isStableClass = false /* code for fixing nested objects override final def isModuleClass: Boolean = @@ -738,26 +743,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => // Does not always work if the rawInfo is a SourcefileLoader, see comment // in "def coreClassesFirst" in Global. - final def exists: Boolean = - this != NoSymbol && (!owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType }) + def exists = !owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType } final def isInitialized: Boolean = validTo != NoPeriod - final def isStableClass: Boolean = { - def hasNoAbstractTypeMember(clazz: Symbol): Boolean = - (clazz hasFlag STABLE) || { - var e = clazz.info.decls.elems - while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym)) - e = e.next - e == null - } - def checkStable() = - (info.baseClasses forall hasNoAbstractTypeMember) && { setFlag(STABLE); true } - isClass && (hasFlag(STABLE) || checkStable()) - } - - /** The variance of this symbol as an integer */ final def variance: Int = if (isCovariant) 1 @@ -788,6 +778,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ------ owner attribute -------------------------------------------------------------- def owner: Symbol = rawowner + // TODO - don't allow the owner to be changed without checking invariants, at least + // when under some flag. Define per-phase invariants for owner/owned relationships, + // e.g. after flatten all classes are owned by package classes, there are lots and + // lots of these to be declared (or more realistically, discovered.) def owner_=(owner: Symbol) { // don't keep the original owner in presentation compiler runs // (the map will grow indefinitely, and the only use case is the @@ -805,11 +799,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => def ownerChain: List[Symbol] = this :: owner.ownerChain def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain - def enclClassChain: List[Symbol] = { - if ((this eq NoSymbol) || isPackageClass) Nil - else if (isClass) this :: owner.enclClassChain - else owner.enclClassChain - } + // Non-classes skip self and return rest of owner chain; overridden in ClassSymbol. + def enclClassChain: List[Symbol] = owner.enclClassChain def ownersIterator: Iterator[Symbol] = new Iterator[Symbol] { private var current = Symbol.this @@ -817,21 +808,21 @@ trait Symbols extends api.Symbols { self: SymbolTable => def next = { val r = current; current = current.owner; r } } - /** same as ownerChain contains sym, but more efficient, and - * with a twist for refinement classes. A refinement class - * has a transowner X if an of its parents has transowner X. + /** Same as `ownerChain contains sym` but more efficient, and + * with a twist for refinement classes (see RefinementClassSymbol.) */ def hasTransOwner(sym: Symbol): Boolean = { var o = this while ((o ne sym) && (o ne NoSymbol)) o = o.owner - (o eq sym) || - isRefinementClass && (info.parents exists (_.typeSymbol.hasTransOwner(sym))) + (o eq sym) } // ------ name attribute -------------------------------------------------------------- def name: Name = rawname + // TODO - don't allow names to be renamed in this unstructured a fashion. + // Rename as little as possible. Enforce invariants on all renames. def name_=(name: Name) { if (name != rawname) { if (owner.isClass) { @@ -903,43 +894,50 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def fullName: String = fullName('.') -// ------ flags attribute -------------------------------------------------------------- + /** + * Symbol creation implementations. + */ + protected def createTypeSymbol(name: TypeName, pos: Position, newFlags: Long): TypeSymbol = + new TypeSymbol(this, pos, name) { } initFlags newFlags - final def flags: Long = { - val fs = rawflags & phase.flagMask - (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) - } - def flags_=(fs: Long) = _rawflags = fs + protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol = + new AbstractTypeSymbol(this, pos, name) initFlags newFlags - /** Set the symbol's flags to the given value, asserting - * that the previous value was 0. - */ - def initFlags(mask: Long): this.type = { - assert(rawflags == 0L, this) - _rawflags = mask - this - } - def setFlag(mask: Long): this.type = { _rawflags = rawflags | mask ; this } - def resetFlag(mask: Long): this.type = { _rawflags = rawflags & ~mask ; this } - final def getFlag(mask: Long): Long = flags & mask - final def resetFlags() { _rawflags = rawflags & TopLevelCreationFlags } + protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol = + new AliasTypeSymbol(this, pos, name) initFlags newFlags - /** Does symbol have ANY flag in `mask` set? */ - final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L + protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem = + new TypeSkolem(this, pos, name, origin) initFlags newFlags - /** Does symbol have ALL the flags in `mask` set? */ - final def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask + protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol = + new ClassSymbol(this, pos, name) initFlags newFlags - /** If the given flag is set on this symbol, also set the corresponding - * notFLAG. For instance if flag is PRIVATE, the notPRIVATE flag will - * be set if PRIVATE is currently set. - */ - final def setNotFlag(flag: Int) = if (hasFlag(flag)) setFlag((flag: @annotation.switch) match { - case PRIVATE => notPRIVATE - case PROTECTED => notPROTECTED - case OVERRIDE => notOVERRIDE - case _ => abort("setNotFlag on invalid flag: " + flag) - }) + protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol = + new ModuleClassSymbol(this, pos, name) initFlags newFlags + + protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol = + new PackageClassSymbol(this, pos, name) initFlags newFlags + + protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol = + new RefinementClassSymbol(this, pos) initFlags newFlags + + protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = + new TermSymbol(this, pos, name) initFlags newFlags + + protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol = + new MethodSymbol(this, pos, name) initFlags newFlags + + protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = + new ModuleSymbol(this, pos, name) initFlags newFlags + + protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol = + new PackageSymbol(this, pos, name) initFlags newFlags + + protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = + new TermSymbol(this, pos, name) initFlags newFlags + + protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = + new TermSymbol(this, pos, name) initFlags newFlags /** The class or term up to which this symbol is accessible, * or RootClass if it is public. As java protected statics are @@ -1008,7 +1006,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => throw CyclicReference(this, tp) } } else { - _rawflags |= LOCKED + rawflags |= LOCKED // activeLocks += 1 // lockedSyms += this } @@ -1200,9 +1198,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => var ph = phase while (ph.prev.keepsTypeParams) ph = ph.prev - // - // if (ph ne phase) - // debuglog("checking unsafeTypeParams(" + this + ") at: " + phase + " reading at: " + ph) ph } @@ -1234,7 +1229,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** The value parameter sections of this symbol. */ def paramss: List[List[Symbol]] = info.paramss - def hasParamWhich(cond: Symbol => Boolean) = paramss exists (_ exists cond) + def hasParamWhich(cond: Symbol => Boolean) = mexists(paramss)(cond) /** The least proper supertype of a class; includes all parent types * and refinement where needed. You need to compute that in a situation like this: @@ -1432,7 +1427,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Internal method to clone a symbol's implementation with the given flags and no info. */ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol - def cloneSymbolImpl(owner: Symbol): Symbol = cloneSymbolImpl(owner, 0L) // ------ access to related symbols -------------------------------------------------- @@ -1443,14 +1437,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod /** The primary constructor of a class. */ - def primaryConstructor: Symbol = { - var c = info.decl( - if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR - else nme.CONSTRUCTOR) - c = if (c hasFlag OVERLOADED) c.alternatives.head else c - //assert(c != NoSymbol) - c - } + def primaryConstructor: Symbol = NoSymbol /** The self symbol (a TermSymbol) of a class with explicit self type, or else the * symbol itself (a TypeSymbol). @@ -1507,6 +1494,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => * is not updated when a module is cloned), or NoSymbol if this is not a ModuleClass. */ def sourceModule: Symbol = NoSymbol + // if (isModuleClass) companionModule else NoSymbol + // NoSymbol /** The implementation class of a trait. If available it will be the * symbol with the same owner, and the name of this symbol with $class @@ -1560,13 +1549,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** The package class containing this symbol, or NoSymbol if there * is not one. */ - def enclosingPackageClass: Symbol = - if (this == NoSymbol) this else { - var packSym = this.owner - while (packSym != NoSymbol && !packSym.isPackageClass) - packSym = packSym.owner - packSym - } + def enclosingPackageClass: Symbol = { + var packSym = this.owner + while (packSym != NoSymbol && !packSym.isPackageClass) + packSym = packSym.owner + packSym + } /** The package containing this symbol, or NoSymbol if there * is not one. */ @@ -1677,21 +1665,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => * Note: does not work for classes owned by methods, see Namers.companionClassOf * * object Foo . companionClass --> class Foo + * + * !!! linkedClassOfClass depends on companionClass on the module class getting + * to the class. As presently implemented this potentially returns class for + * any symbol except NoSymbol. */ - final def companionClass: Symbol = { - if (this != NoSymbol) - flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this) - else NoSymbol - } - - /** A helper method that factors the common code used the discover a - * companion module of a class. If a companion module exists, its symbol is - * returned, otherwise, `NoSymbol` is returned. The method assumes that - * `this` symbol has already been checked to be a class (using `isClass`). - */ - private final def companionModule0: Symbol = - flatOwnerInfo.decl(name.toTermName).suchThat( - sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod) + def companionClass: Symbol = flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this) /** For a class: the module or case class factory with the same name in the same package. * For all others: NoSymbol @@ -1699,9 +1678,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * * class Foo . companionModule --> object Foo */ - final def companionModule: Symbol = - if (isClass && !isRefinementClass) companionModule0 - else NoSymbol + def companionModule: Symbol = NoSymbol /** For a module: its linked class * For a plain class: its linked module or case factory. @@ -1709,18 +1686,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => * * class Foo <-- companionSymbol --> object Foo */ - final def companionSymbol: Symbol = - if (isTerm) companionClass - else if (isClass) companionModule0 - else NoSymbol + def companionSymbol: Symbol = NoSymbol /** For a module class: its linked class * For a plain class: the module class of its linked module. * * class Foo <-- linkedClassOfClass --> class Foo$ */ - final def linkedClassOfClass: Symbol = - if (isModuleClass) companionClass else companionModule.moduleClass + def linkedClassOfClass: Symbol = NoSymbol /** * Returns the rawInfo of the owner. If the current phase has flat classes, @@ -1733,7 +1706,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * symbol B in the decls of p. So to find a linked symbol ("object B" or "class B") * we need to apply flatten to B first. Fixes #2470. */ - private final def flatOwnerInfo: Type = { + protected final def flatOwnerInfo: Type = { if (needsFlatClasses) info owner.rawInfo @@ -1912,23 +1885,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => case p :: _ => p case _ => NoSymbol } - - /** change name by appending $$<fully-qualified-name-of-class `base`> - * Do the same for any accessed symbols or setters/getters - */ - def expandName(base: Symbol) { - if (this.isTerm && this != NoSymbol && !hasFlag(EXPANDEDNAME)) { - setFlag(EXPANDEDNAME) - if (hasAccessorFlag && !isDeferred) { - accessed.expandName(base) - } else if (hasGetter) { - getter(owner).expandName(base) - setter(owner).expandName(base) - } - name = nme.expandedName(name.toTermName, base) - if (isType) name = name - } - } /* code for fixing nested objects def expandModuleClassName() { name = newTypeName(name.toString + "$") @@ -1953,7 +1909,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this - def orElse[T](alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt + @inline final def orElse[T](alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt // ------ toString ------------------------------------------------------------------- @@ -2115,31 +2071,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def infosString = infos.toString def debugLocationString = fullLocationString + " " + debugFlagString - def debugFlagString = hasFlagsToString(-1L) - def hasFlagsToString(mask: Long): String = flagsToString( - flags & mask, - if (hasAccessBoundary) privateWithin.toString else "" - ) - - /** String representation of symbol's variance */ - def varianceString: String = - if (variance == 1) "+" - else if (variance == -1) "-" - else "" - - def defaultFlagMask = - if (isAbstractType) ExplicitFlags - else if (settings.debug.value) -1L - else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE - else ExplicitFlags - - // make the error message more googlable - def flagsExplanationString = - if (isGADTSkolem) " (this is a GADT skolem)" - else "" - def accessString = hasFlagsToString(PRIVATE | PROTECTED | LOCAL) - def defaultFlagString = hasFlagsToString(defaultFlagMask) private def defStringCompose(infoString: String) = compose( defaultFlagString, keyString, @@ -2171,12 +2103,24 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class for term symbols */ class TermSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) extends Symbol(initOwner, initPos, initName) { - final override def isTerm = true + private[this] var _referenced: Symbol = NoSymbol + privateWithin = NoSymbol + final override def isTerm = true override def name: TermName = rawname.toTermName - privateWithin = NoSymbol + override def companionSymbol: Symbol = companionClass + override def moduleClass = if (isModule) referenced else NoSymbol - private[this] var _referenced: Symbol = NoSymbol + override def hasDefault = this hasFlag DEFAULTPARAM // overloaded with TRAIT + override def isBridge = this hasFlag BRIDGE + override def isEarlyInitialized = this hasFlag PRESUPER + override def isMethod = this hasFlag METHOD + override def isModule = this hasFlag MODULE + override def isOverloaded = this hasFlag OVERLOADED + override def isPackage = this hasFlag PACKAGE + override def isValueParameter = this hasFlag PARAM + + override def isPackageObject = isModule && (name == nme.PACKAGE) def referenced: Symbol = _referenced def referenced_=(x: Symbol) { _referenced = x } @@ -2210,11 +2154,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (name endsWith nme.OUTER) initialize.referenced else NoSymbol - override def moduleClass: Symbol = - if (hasFlag(MODULE)) referenced else NoSymbol - def setModuleClass(clazz: Symbol): TermSymbol = { - assert(hasFlag(MODULE), this) + assert(isModule, this) referenced = clazz this } @@ -2230,6 +2171,23 @@ trait Symbols extends api.Symbols { self: SymbolTable => referenced } + /** change name by appending $$<fully-qualified-name-of-class `base`> + * Do the same for any accessed symbols or setters/getters + */ + override def expandName(base: Symbol) { + if (!hasFlag(EXPANDEDNAME)) { + setFlag(EXPANDEDNAME) + if (hasAccessorFlag && !isDeferred) { + accessed.expandName(base) + } + else if (hasGetter) { + getter(owner).expandName(base) + setter(owner).expandName(base) + } + name = nme.expandedName(name.toTermName, base) + } + } + protected def doCookJavaRawInfo() { def cook(sym: Symbol) { require(sym.isJavaDefined, sym) @@ -2263,9 +2221,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class for module symbols */ class ModuleSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) - extends TermSymbol(initOwner, initPos, initName) { + extends TermSymbol(initOwner, initPos, initName) with DistinguishingFlag { + def distinguishingFlag = MODULE + private var flatname: TermName = null + override def isModule = true + override def moduleClass = referenced + override def companionClass = + flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this) + override def owner = ( if (!isMethod && needsFlatClasses) rawowner.owner else rawowner @@ -2279,21 +2244,38 @@ trait Symbols extends api.Symbols { self: SymbolTable => } else rawname.toTermName ) + } - override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = - owner.newModuleSymbol(name, pos, newFlags).copyAttrsFrom(this) + class PackageSymbol protected[Symbols] (owner0: Symbol, pos0: Position, name0: TermName) + extends ModuleSymbol(owner0, pos0, name0) with DistinguishingFlag { + override def distinguishingFlag = super.distinguishingFlag | PACKAGE + override def isPackage = true } /** A class for method symbols */ class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) - extends TermSymbol(initOwner, initPos, initName) { - private var mtpePeriod = NoPeriod - private var mtpePre: Type = _ - private var mtpeResult: Type = _ - private var mtpeInfo: Type = _ - - override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = - owner.newMethodSymbol(name, pos, newFlags).copyAttrsFrom(this) + extends TermSymbol(initOwner, initPos, initName) with DistinguishingFlag { + def distinguishingFlag = METHOD + // MethodSymbols pick up MODULE when trait-owned object accessors are cloned + // during mixin composition. + override protected def neverHasFlags = super.neverHasFlags & ~MODULE + + private[this] var mtpePeriod = NoPeriod + private[this] var mtpePre: Type = _ + private[this] var mtpeResult: Type = _ + private[this] var mtpeInfo: Type = _ + + override def isMethod = true + override def isMacro = this hasFlag MACRO + override def isVarargsMethod = this hasFlag VARARGS + override def isLiftedMethod = this hasFlag LIFTED + // TODO - this seems a strange definition for "isSourceMethod", given that + // it does not make any specific effort to exclude synthetics. Figure out what + // this method is really for and what logic makes sense. + override def isSourceMethod = !(this hasFlag STABLE) // exclude all accessors + // unfortunately having the CASEACCESSOR flag does not actually mean you + // are a case accessor (you can also be a field.) + override def isCaseAccessorMethod = isCaseAccessor def typeAsMemberOf(pre: Type): Type = { if (mtpePeriod == currentPeriod) { @@ -2313,38 +2295,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { - // Temporary programmatic help tracking down who might do such a thing - override def setFlag(mask: Long): this.type = { - if (isSetting(DEFERRED, mask)) { - println("Setting DEFERRED on alias at") - (new Throwable).printStackTrace - } - super.setFlag(mask) - } final override def isAliasType = true - override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AliasTypeSymbol = - owner.newAliasTypeSymbol(name, pos, newFlags) - } - - class AbstractTypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) - extends TypeSymbol(initOwner, initPos, initName) with AbstractTypeMixin { - override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AbstractTypeSymbol = - owner.newAbstractTypeSymbol(name, pos, newFlags) } - /** Might be mixed into TypeSymbol or TypeSkolem. - */ - trait AbstractTypeMixin extends TypeSymbol { - override def resetFlag(mask: Long): this.type = { - // Temporary programmatic help tracking down who might do such a thing - if (settings.debug.value) { - if (isClearing(DEFERRED, mask)) { - println("Clearing DEFERRED on abstract type at") - (new Throwable).printStackTrace - } - } - super.resetFlag(mask) - } + class AbstractTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) + extends TypeSymbol(initOwner, initPos, initName) { final override def isAbstractType = true override def existentialBound = this.info } @@ -2352,33 +2307,36 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class of type symbols. Alias and abstract types are direct instances * of this class. Classes are instances of a subclass. */ - abstract class TypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) { + abstract class TypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) + extends Symbol(initOwner, initPos, initName) { privateWithin = NoSymbol + + final override def isType = true + override def isNonClassType = true + private var tyconCache: Type = null private var tyconRunId = NoRunId private var tpeCache: Type = _ private var tpePeriod = NoPeriod + override def isAbstractType = this hasFlag DEFERRED + override def isContravariant = this hasFlag CONTRAVARIANT + override def isCovariant = this hasFlag COVARIANT + override def isExistentialQuantified = isExistentiallyBound && !isSkolem + override def isExistentiallyBound = this hasFlag EXISTENTIAL + override def isTypeParameter = isTypeParameterOrSkolem && !isSkolem + override def isTypeParameterOrSkolem = this hasFlag PARAM + /** Overridden in subclasses for which it makes sense. */ def existentialBound: Type = abort("unexpected type: "+this.getClass+ " "+debugLocationString) + // a type symbol bound by an existential type, for instance the T in + // List[T] forSome { type T } + override def name: TypeName = super.name.toTypeName - final override def isType = true - override def isNonClassType = true - override def isAbstractType = { - if (settings.debug.value) { - if (isDeferred) { - println("TypeSymbol claims to be abstract type: " + this.getClass + " " + debugFlagString + " at ") - (new Throwable).printStackTrace - } - } - isDeferred - } - private def newTypeRef(targs: List[Type]) = { - val pre = if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType - typeRef(pre, this, targs) - } + private def newPrefix = if (this hasFlag EXISTENTIAL | PARAM) NoPrefix else owner.thisType + private def newTypeRef(targs: List[Type]) = typeRef(newPrefix, this, targs) /** Let's say you have a type definition * @@ -2471,8 +2429,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } + /** Default implementation. */ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = - owner.newTypeSymbol(name, pos, newFlags) + owner.newNonClassSymbol(name, pos, newFlags) incCounter(typeSymbolCount) } @@ -2492,12 +2451,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ class TypeSkolem protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef) extends TypeSymbol(initOwner, initPos, initName) { - /** The skolemization level in place when the skolem was constructed */ val level = skolemizationLevel final override def isSkolem = true + override def isGADTSkolem = this hasFlag CASEACCESSOR | SYNTHETIC + override def isTypeSkolem = this hasFlag PARAM + override def isExistentialSkolem = this hasFlag EXISTENTIAL + override def isAbstractType = this hasFlag DEFERRED + + override def isExistentialQuantified = false + override def existentialBound = if (isAbstractType) this.info else super.existentialBound + /** If typeskolem comes from a type parameter, that parameter, otherwise skolem itself */ override def deSkolemize = origin match { case s: Symbol => s @@ -2521,17 +2487,92 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class for class symbols */ class ClassSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { - private[this] var flatname: TypeName = null - private[this] var source: AbstractFileType = null - private[this] var thissym: Symbol = this + private[this] var flatname: TypeName = _ + private[this] var source: AbstractFileType = _ + private[this] var thissym: Symbol = this + + private[this] var thisTypeCache: Type = _ + private[this] var thisTypePeriod = NoPeriod + private[this] var typeOfThisCache: Type = _ + private[this] var typeOfThisPeriod = NoPeriod + + override protected def alwaysHasFlags: Long = 0L + override protected def neverHasFlags: Long = 0L final override def isClass = true final override def isNonClassType = false final override def isAbstractType = false final override def isAliasType = false + override def isAbstractClass = this hasFlag ABSTRACT + override def isClassLocalToConstructor = this hasFlag INCONSTRUCTOR + override def isImplClass = this hasFlag IMPLCLASS + override def isModuleClass = this hasFlag MODULE + override def isPackageClass = this hasFlag PACKAGE + override def isTrait = this hasFlag TRAIT + + override def isConcreteClass = !(this hasFlag ABSTRACT | TRAIT) + override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE) + + def isTraitOrImplClass = this hasFlag TRAIT | IMPLCLASS + def isNonImplModuleClass = isModuleClass && !isImplClass + + override def isAnonymousClass = name containsName tpnme.ANON_CLASS_NAME + override def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass + override def isNestedClass = !owner.isPackageClass + override def isNumericValueClass = definitions.isNumericValueClass(this) + override def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this) + + /** Is this class locally defined? + * A class is local, if + * - it is anonymous, or + * - its owner is a value + * - it is defined within a local class + */ + override def isLocalClass = ( + isAnonOrRefinementClass + || isLocal + || !owner.isPackageClass && owner.isLocalClass + ) + override def isStableClass = (this hasFlag STABLE) || checkStable() + + private def checkStable() = { + def hasNoAbstractTypeMember(clazz: Symbol): Boolean = + (clazz hasFlag STABLE) || { + var e = clazz.info.decls.elems + while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym)) + e = e.next + e == null + } + (info.baseClasses forall hasNoAbstractTypeMember) && { + setFlag(STABLE) + true + } + } + + override def enclClassChain = this :: owner.enclClassChain + + /** A helper method that factors the common code used the discover a + * companion module of a class. If a companion module exists, its symbol is + * returned, otherwise, `NoSymbol` is returned. + */ + protected final def companionModule0: Symbol = + flatOwnerInfo.decl(name.toTermName).suchThat( + sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod) + + override def companionModule = companionModule0 + override def companionSymbol = companionModule0 + override def linkedClassOfClass = companionModule.moduleClass + override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound)) + def primaryConstructorName = if (isTraitOrImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR + + override def primaryConstructor = { + val c = info decl primaryConstructorName + if (c.isOverloaded) c.alternatives.head else c + } + override def sourceFile = if (owner.isPackageClass) source else super.sourceFile @@ -2542,12 +2583,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => thissym = this } - private var thisTypeCache: Type = _ - private var thisTypePeriod = NoPeriod - - private var typeOfThisCache: Type = _ - private var typeOfThisPeriod = NoPeriod - /** the type this.type in this class */ override def thisType: Type = { val period = thisTypePeriod @@ -2558,8 +2593,24 @@ trait Symbols extends api.Symbols { self: SymbolTable => thisTypeCache } + /** the self type of an object foo is foo.type, not class<foo>.this.type + */ + override def typeOfThis: Type = { + if (isNonImplModuleClass && owner != NoSymbol) { + val period = typeOfThisPeriod + if (period != currentPeriod) { + typeOfThisPeriod = currentPeriod + if (!isValid(period)) + typeOfThisCache = singleType(owner.thisType, sourceModule) + } + typeOfThisCache + } + else thisSym.tpe + } + override def owner: Symbol = if (needsFlatClasses) rawowner.owner else rawowner + override def name: TypeName = ( if (needsFlatClasses) { if (flatname eq null) @@ -2573,27 +2624,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A symbol carrying the self type of the class as its type */ override def thisSym: Symbol = thissym - /** the self type of an object foo is foo.type, not class<foo>.this.type - */ - override def typeOfThis: Type = { - if (getFlag(MODULE | IMPLCLASS) == MODULE.toLong && owner != NoSymbol) { - val period = typeOfThisPeriod - if (period != currentPeriod) { - typeOfThisPeriod = currentPeriod - if (!isValid(period)) - typeOfThisCache = singleType(owner.thisType, sourceModule) - } - typeOfThisCache - } - else thisSym.tpe - } - /** Sets the self type of the class */ override def typeOfThis_=(tp: Type) { thissym = newThisSym(pos).setInfo(tp) } - override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = { + override def cloneSymbolImpl(owner: Symbol, newFlags: Long): ClassSymbol = { val clone = owner.newClassSymbol(name, pos, newFlags) if (thisSym != this) { clone.typeOfThis = typeOfThis @@ -2602,12 +2638,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => clone } - override def sourceModule = - if (isModuleClass) companionModule else NoSymbol + // Must have this line. + override def sourceModule = if (isModuleClass) companionModule else NoSymbol override def firstParamAccessor = - info.decls.find(m => (m hasFlag PARAMACCESSOR) && m.isMethod) getOrElse NoSymbol - + info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse NoSymbol private[this] var childSet: Set[Symbol] = Set() override def children = childSet @@ -2621,12 +2656,17 @@ trait Symbols extends api.Symbols { self: SymbolTable => * plain class symbols! */ class ModuleClassSymbol protected[Symbols] (owner: Symbol, pos: Position, name: TypeName) - extends ClassSymbol(owner, pos, name) { + extends ClassSymbol(owner, pos, name) with DistinguishingFlag { + def distinguishingFlag = MODULE + private var module: Symbol = null - private var implicitMembersCacheValue: List[Symbol] = List() + private var implicitMembersCacheValue: List[Symbol] = Nil private var implicitMembersCacheKey1: Type = NoType private var implicitMembersCacheKey2: ScopeEntry = null + override def isModuleClass = true + override def linkedClassOfClass = companionClass + def implicitMembers: List[Symbol] = { val tp = info if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) { @@ -2644,6 +2684,35 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def sourceModule_=(module: Symbol) { this.module = module } } + class PackageClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position, name0: TypeName) + extends ModuleClassSymbol(owner0, pos0, name0) with DistinguishingFlag { + override def distinguishingFlag = super.distinguishingFlag | PACKAGE + override def sourceModule = companionModule + override def enclClassChain = Nil + override def isPackageClass = true + } + + class RefinementClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position) + extends ClassSymbol(owner0, pos0, tpnme.REFINE_CLASS_NAME) { + override def name_=(name: Name) { + assert(false, "Cannot set name of RefinementClassSymbol to " + name) + super.name_=(name) + } + override def isRefinementClass = true + override def isAnonOrRefinementClass = true + override def isLocalClass = true + override def hasMeaninglessName = true + override def companionModule: Symbol = NoSymbol + + /** The mentioned twist. A refinement class has transowner X + * if any of its parents has transowner X. + */ + override def hasTransOwner(sym: Symbol) = ( + super.hasTransOwner(sym) + || info.parents.exists(_.typeSymbol hasTransOwner sym) + ) + } + class FreeVar(name0: TermName, val value: Any) extends TermSymbol(NoSymbol, NoPosition, name0) { override def hashCode = if (value == null) 0 else value.hashCode override def equals(other: Any): Boolean = other match { @@ -2663,12 +2732,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => unlock() validTo = currentPeriod } + override def defaultFlagMask = AllFlags + override def exists = false + override def isHigherOrderTypeParameter = false + override def companionClass = NoSymbol + override def companionModule = NoSymbol + override def companionSymbol = NoSymbol override def isSubClass(that: Symbol) = false override def filter(cond: Symbol => Boolean) = this override def defString: String = toString override def locationString: String = "" + override def enclClassChain = Nil override def enclClass: Symbol = this override def enclosingTopLevelClass: Symbol = this + override def enclosingPackageClass: Symbol = this override def enclMethod: Symbol = this override def sourceFile: AbstractFileType = null override def ownerChain: List[Symbol] = List() @@ -2689,9 +2766,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)") } - protected def makeNoSymbol = new NoSymbol + protected def makeNoSymbol: NoSymbol = new NoSymbol - lazy val NoSymbol = makeNoSymbol + lazy val NoSymbol: NoSymbol = makeNoSymbol /** Derives a new list of symbols from the given list by mapping the given * list across the given function. Then fixes the info of all the new symbols @@ -2779,7 +2856,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class for type histories */ private sealed case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) { assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this) - assert(validFrom != NoPeriod) + assert(validFrom != NoPeriod, this) + override def toString() = "TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")" diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index 8ed0ee6357..7a084304a8 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -175,7 +175,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => printAnnotations(tree) printModifiers(tree, mods) val word = - if (mods.hasTraitFlag) "trait" + if (mods.isTrait) "trait" else if (ifSym(tree, _.isModuleClass)) "object" else "class" diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index f1ec64bda9..f89aa9bf5c 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -257,12 +257,11 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { } def isModuleFlag = (flags & MODULE) != 0L - def isMethodFlag = (flags & METHOD) != 0L def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) def isModuleRoot = (name == moduleRoot.name) && (owner == moduleRoot.owner) + def pflags = flags & PickledFlags def finishSym(sym: Symbol): Symbol = { - sym.flags = flags & PickledFlags sym.privateWithin = privateWithin sym.info = ( if (atEnd) { @@ -282,27 +281,27 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { } finishSym(tag match { - case TYPEsym => owner.newAbstractType(name.toTypeName) - case ALIASsym => owner.newAliasType(name.toTypeName) + case TYPEsym | ALIASsym => + owner.newNonClassSymbol(name.toTypeName, NoPosition, pflags) case CLASSsym => - val sym = (isClassRoot, isModuleFlag) match { - case (true, true) => moduleRoot.moduleClass - case (true, false) => classRoot - case (false, true) => owner.newModuleClass(name.toTypeName) - case (false, false) => owner.newClass(name.toTypeName) - } + val sym = ( + if (isClassRoot) { + if (isModuleFlag) moduleRoot.moduleClass setFlag pflags + else classRoot setFlag pflags + } + else owner.newClassSymbol(name.toTypeName, NoPosition, pflags) + ) if (!atEnd) sym.typeOfThis = newLazyTypeRef(readNat()) sym case MODULEsym => val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... () - if (isModuleRoot) moduleRoot - else owner.newLinkedModule(clazz) + if (isModuleRoot) moduleRoot setFlag pflags + else owner.newLinkedModule(clazz, pflags) case VALsym => if (isModuleRoot) { assert(false); NoSymbol } - else if (isMethodFlag) owner.newMethod(name.toTermName) - else owner.newValue(name.toTermName) + else owner.newTermSymbol(name.toTermName, NoPosition, pflags) case _ => errorBadSignature("bad symbol tag: " + tag) diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala index 3f2fa30be2..85f7b56920 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala @@ -17,7 +17,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar = new FreeVar(name, value) with SynchronizedTermSymbol initFlags newFlags setInfo tpe - override protected def makeNoSymbol = new NoSymbol with SynchronizedSymbol + override protected def makeNoSymbol: NoSymbol = new NoSymbol with SynchronizedSymbol trait SynchronizedSymbol extends Symbol { @@ -55,32 +55,45 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => // ------ creators ------------------------------------------------------------------- - override def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = - new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + override protected def createTypeSymbol(name: TypeName, pos: Position, newFlags: Long): TypeSymbol = + new TypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags - override def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol = + override protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol = new AbstractTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags - override def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol = + override protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol = new AliasTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags - override def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = - new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags - - override def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol = - new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags + override protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem = + new TypeSkolem(this, pos, name, origin) with SynchronizedTypeSymbol initFlags newFlags - override def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = + override protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol = new ClassSymbol(this, pos, name) with SynchronizedClassSymbol initFlags newFlags - override def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = + override protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol = new ModuleClassSymbol(this, pos, name) with SynchronizedModuleClassSymbol initFlags newFlags - override def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem = - if ((newFlags & DEFERRED) == 0L) - new TypeSkolem(this, pos, name, origin) with SynchronizedTypeSymbol initFlags newFlags - else - new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin with SynchronizedTypeSymbol initFlags newFlags + override protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol = + new PackageClassSymbol(this, pos, name) with SynchronizedModuleClassSymbol initFlags newFlags + + override protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol = + new RefinementClassSymbol(this, pos) with SynchronizedClassSymbol initFlags newFlags + + override protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = + new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + + override protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol = + new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags + + override protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = + new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + + override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol = + new PackageSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + + // TODO + // override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long) + // override protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long) } // ------- subclasses --------------------------------------------------------------------- diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 6a30dc2a0f..8df687eca9 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -220,10 +220,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb (settings.log.isSetByUser) && ((settings.log containsPhase globalPhase) || (settings.log containsPhase phase)) ) - def atPhaseStackMessage = atPhaseStack match { - case Nil => "" - case ps => ps.reverseMap("->" + _).mkString("(", " ", ")") - } // Over 200 closure objects are eliminated by inlining this. @inline final def log(msg: => AnyRef) { if (shouldLogAtThisPhase) diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala index 7ece8bbd31..04468a096d 100644 --- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -199,7 +199,7 @@ trait Reifiers { self: Global => ValDef(NoMods, localName(sym), TypeTree(), Apply( Select(reify(sym.owner), "newNestedSymbol"), - List(reify(sym.name), reify(sym.pos), Literal(Constant(sym.flags))) + List(reify(sym.name), reify(sym.pos), Literal(Constant(sym.flags)), Literal(Constant(sym.isClass))) ) ) } diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index 9f361e5bcc..569cb4977b 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -44,7 +44,7 @@ abstract class TreeInfo extends reflect.internal.TreeInfo { } def isInterface(mods: HasFlags, body: List[Tree]) = - mods.hasTraitFlag && (body forall isInterfaceMember) + mods.isTrait && (body forall isInterfaceMember) def isAllowedInUniversalTrait(stat: Tree): Boolean = stat match { case _: ValDef => false diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 45325b4694..fa2fc54ac0 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2600,7 +2600,6 @@ self => in.nextToken val nameOffset = in.offset val name = identForType() - def isTrait = mods.hasTraitFlag atPos(start, if (name == tpnme.ERROR) start else nameOffset) { savingClassContextBounds { @@ -2608,16 +2607,16 @@ self => val tparams = typeParamClauseOpt(name, contextBoundBuf) classContextBounds = contextBoundBuf.toList val tstart = in.offset :: classContextBounds.map(_.pos.startOrPoint) min; - if (!classContextBounds.isEmpty && isTrait) { + if (!classContextBounds.isEmpty && mods.isTrait) { syntaxError("traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'", false) classContextBounds = List() } val constrAnnots = constructorAnnotations() val (constrMods, vparamss) = - if (isTrait) (Modifiers(Flags.TRAIT), List()) + if (mods.isTrait) (Modifiers(Flags.TRAIT), List()) else (accessModifierOpt(), paramClauses(name, classContextBounds, mods.isCase)) var mods1 = mods - if (isTrait) { + if (mods.isTrait) { if (settings.YvirtClasses && in.token == SUBTYPE) mods1 |= Flags.DEFERRED } else if (in.token == SUBTYPE) { syntaxError("classes are not allowed to be virtual", false) @@ -2709,7 +2708,7 @@ self => } def isInterface(mods: Modifiers, body: List[Tree]): Boolean = - mods.hasTraitFlag && (body forall treeInfo.isInterfaceMember) + mods.isTrait && (body forall treeInfo.isInterfaceMember) /** {{{ * ClassTemplateOpt ::= `extends' ClassTemplate | [[`extends'] TemplateBody] @@ -2719,9 +2718,9 @@ self => */ def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]], tstart: Int): Template = { val (parents0, argss, self, body) = ( - if (in.token == EXTENDS || in.token == SUBTYPE && mods.hasTraitFlag) { + if (in.token == EXTENDS || in.token == SUBTYPE && mods.isTrait) { in.nextToken() - template(mods.hasTraitFlag) + template(mods.isTrait) } else { newLineOptWhenFollowedBy(LBRACE) diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index 2ff0c1926c..7ad7cadd92 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -142,7 +142,7 @@ trait TypeKinds { self: ICodes => def lub0(tk1: TypeKind, tk2: TypeKind): Type = beforeUncurry { import definitions._ val tp = global.lub(List(tk1.toType, tk2.toType)) - val (front, rest) = tp.parents span (_.typeSymbol.hasTraitFlag) + val (front, rest) = tp.parents span (_.typeSymbol.isTrait) if (front.isEmpty || rest.isEmpty || rest.head.typeSymbol == ObjectClass) tp else rest.head diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 39e2cbe694..dde166d64b 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -43,11 +43,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => */ private def isInterfaceMember(sym: Symbol) = ( sym.isType || { - // !!! Shouldn't the following code be equivalent to leaving - // out the "sym.info" call and starting with "sym.initialize.isMethod" ? - // Because, it is not, which I found a little disturbing. The compiler - // fails to bootstrap with an error somewhere. - sym.info // initialize to set lateMETHOD flag if necessary + sym.info // initialize to set lateMETHOD flag if necessary ( sym.isMethod && !sym.isLabel @@ -71,6 +67,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => /** Return the implementation class of a trait; create a new one of one does not yet exist */ def implClass(iface: Symbol): Symbol = { iface.info + def implClassFlags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS implClassMap.getOrElse(iface, { atPhase(implClassPhase) { @@ -101,7 +98,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => else log("not unlinking existing " + impl + " as the impl class is not visible on the classpath.") } if (impl == NoSymbol) { - impl = iface.cloneSymbolImpl(iface.owner) + impl = iface.cloneSymbolImpl(iface.owner, implClassFlags) impl.name = implName impl.sourceFile = iface.sourceFile if (iface.owner.isClass) @@ -109,7 +106,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile impl setPos iface.pos - impl.flags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS + impl.flags = implClassFlags impl setInfo new LazyImplClassType(iface) implClassMap(iface) = impl debuglog( diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 595c1486b6..16c7c3c3ff 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -93,7 +93,7 @@ abstract class ExplicitOuter extends InfoTransform } def newOuterAccessor(clazz: Symbol) = { val accFlags = SYNTHETIC | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 ) - val sym = clazz.newMethodSymbol(nme.OUTER, clazz.pos, accFlags) + val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags) val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType sym expandName clazz diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index 8856024a30..ac76862094 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -108,7 +108,7 @@ abstract class Flatten extends InfoTransform { tree match { case PackageDef(_, _) => liftedDefs(tree.symbol.moduleClass) = new ListBuffer - case Template(_, _, _) if tree.symbol.owner.hasPackageFlag => + case Template(_, _, _) if tree.symbol.isDefinedInPackage => liftedDefs(tree.symbol.owner) = new ListBuffer case _ => } diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 49ddb985dc..ff0bdf7580 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -661,7 +661,7 @@ trait ContextErrors { } private def ambiguousErrorMsgPos(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String) = - if (sym1.hasDefaultFlag && sym2.hasDefaultFlag && sym1.enclClass == sym2.enclClass) { + if (sym1.hasDefault && sym2.hasDefault && sym1.enclClass == sym2.enclClass) { val methodName = nme.defaultGetterToMethod(sym1.name) (sym1.enclClass.pos, "in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName + diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index dba31f7bca..ebf8e3fc9a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -699,7 +699,7 @@ trait Infer { case NamedType(name, _) => Some(name) case _ => None })._1 - if (missing forall (_.hasDefaultFlag)) { + if (missing forall (_.hasDefault)) { // add defaults as named arguments val argtpes1 = argtpes0 ::: (missing map (p => NamedType(p.name, p.tpe))) isApplicable(undetparams, ftpe, argtpes1, pt) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 1b505d1e5d..7ea78a81d5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -529,7 +529,7 @@ trait Namers extends MethodSynthesis { def enterCopyMethodOrGetter(tree: Tree, tparams: List[TypeDef]): Symbol = { val sym = tree.symbol val lazyType = completerOf(tree, tparams) - def completeCopyFirst = sym.isSynthetic && (!sym.hasDefaultFlag || sym.owner.info.member(nme.copy).isSynthetic) + def completeCopyFirst = sym.isSynthetic && (!sym.hasDefault || sym.owner.info.member(nme.copy).isSynthetic) def completeCopyMethod(clazz: Symbol) { // the 'copy' method of case classes needs a special type completer to make // bug0054.scala (and others) work. the copy method has to take exactly the same @@ -1045,7 +1045,7 @@ trait Namers extends MethodSynthesis { } ) // #2382: return type of default getters are always @uncheckedVariance - if (meth.hasDefaultFlag) + if (meth.hasDefault) rt.withAnnotation(AnnotationInfo(uncheckedVarianceClass.tpe, List(), List())) else rt }) @@ -1095,8 +1095,8 @@ trait Namers extends MethodSynthesis { for (vparam <- vparams) { val sym = vparam.symbol // true if the corresponding parameter of the base class has a default argument - val baseHasDefault = overrides && baseParams.head.hasDefaultFlag - if (sym.hasDefaultFlag) { + val baseHasDefault = overrides && baseParams.head.hasDefault + if (sym.hasDefault) { // generate a default getter for that argument val oflag = if (baseHasDefault) OVERRIDE else 0 val name = nme.defaultGetterName(meth.name, posCounter) diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index c621497618..2573678f8c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -377,7 +377,7 @@ trait NamesDefaults { self: Analyzer => pos: util.Position, context: Context): (List[Tree], List[Symbol]) = { if (givenArgs.length < params.length) { val (missing, positional) = missingParams(givenArgs, params) - if (missing forall (_.hasDefaultFlag)) { + if (missing forall (_.hasDefault)) { val defaultArgs = missing flatMap (p => { val defGetter = defaultGetter(p, context) // TODO #3649 can create spurious errors when companion object is gone (because it becomes unlinked from scope) @@ -399,7 +399,7 @@ trait NamesDefaults { self: Analyzer => } }) (givenArgs ::: defaultArgs, Nil) - } else (givenArgs, missing filterNot (_.hasDefaultFlag)) + } else (givenArgs, missing filterNot (_.hasDefault)) } else (givenArgs, Nil) } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 54b711cebc..5a7c015f09 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -123,7 +123,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R defaultMethodNames.distinct foreach { name => val methods = clazz.info.findMember(name, 0L, METHOD, false).alternatives - val haveDefaults = methods filter (sym => sym.hasParamWhich(_.hasDefaultFlag) && !nme.isProtectedAccessorName(sym.name)) + val haveDefaults = methods filter (sym => sym.hasParamWhich(_.hasDefault) && !nme.isProtectedAccessorName(sym.name)) if (haveDefaults.lengthCompare(1) > 0) { val owners = haveDefaults map (_.owner) @@ -381,7 +381,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R overrideError("cannot be used here - class definitions cannot be overridden"); } else if (!other.isDeferred && member.isClass) { overrideError("cannot be used here - classes can only override abstract types"); - } else if (other.isFinal) { // (1.2) + } else if (other.isEffectivelyFinal) { // (1.2) overrideError("cannot override final member"); // synthetic exclusion needed for (at least) default getters. } else if (!other.isDeferred && !member.isAnyOverride && !member.isSynthetic) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 36c81b09cd..76e1d40af9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1922,7 +1922,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { rhs1 = checkDead(rhs1) if (!isPastTyper && meth.owner.isClass && - meth.paramss.exists(ps => ps.exists(_.hasDefaultFlag) && isRepeatedParamType(ps.last.tpe))) + meth.paramss.exists(ps => ps.exists(_.hasDefault) && isRepeatedParamType(ps.last.tpe))) StarWithDefaultError(meth) if (!isPastTyper) { @@ -2492,7 +2492,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe) || e.sym.isMacro && e1.sym.isMacro)) // default getters are defined twice when multiple overloads have defaults. an // error for this is issued in RefChecks.checkDefaultsInOverloaded - if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag && + if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefault && !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) { log("Double definition detected:\n " + ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " + @@ -3106,7 +3106,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { for (sym <- names) { // make sure the flags are up to date before erroring (jvm/t3415 fails otherwise) sym.initialize - if (!sym.hasAnnotation(AnnotationDefaultAttr) && !sym.hasDefaultFlag) + if (!sym.hasAnnotation(AnnotationDefaultAttr) && !sym.hasDefault) reportAnnotationError(AnnotationMissingArgError(ann, annType, sym)) } diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala index 44dc2ce1c2..383312b8f5 100755 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/library/scala/reflect/api/Symbols.scala @@ -183,7 +183,7 @@ trait Symbols { self: Universe => /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has * the current symbol as its owner. */ - def newNestedSymbol(name: Name, pos: Position, flags: Long): Symbol // needed by LiftCode + def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol // needed by LiftCode /** Low-level operation to set the symbol's flags * @return the symbol itself diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 4ee13adf52..d8180fe029 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -298,7 +298,6 @@ trait Trees { self: Universe => case ValDef(mods, _, _, _) => if (mods hasModifier Modifier.mutable) "var" else "val" case _ => "" } - // final def hasFlag(mask: Long): Boolean = mods hasFlag mask } /** A packaging, such as `package pid { stats }` diff --git a/test/files/scalap/caseClass/result.test b/test/files/scalap/caseClass/result.test index 7dfe3a0356..6165444026 100644 --- a/test/files/scalap/caseClass/result.test +++ b/test/files/scalap/caseClass/result.test @@ -14,3 +14,9 @@ case class CaseClass[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) override def toString() : java.lang.String = { /* compiled code */ } override def equals(x$1 : scala.Any) : scala.Boolean = { /* compiled code */ } } +object CaseClass extends scala.AnyRef with scala.Serializable { + def this() = { /* compiled code */ } + final override def toString() : java.lang.String = { /* compiled code */ } + def apply[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) : CaseClass[A] = { /* compiled code */ } + def unapply[A <: scala.Seq[scala.Int]](x$0 : CaseClass[A]) : scala.Option[scala.Tuple2[A, scala.Predef.String]] = { /* compiled code */ } +} |