summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Symbols.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/scala/reflect/internal/Symbols.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala3190
1 files changed, 3190 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
new file mode 100644
index 0000000000..86693cf880
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -0,0 +1,3190 @@
+ /* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package internal
+
+import scala.collection.{ mutable, immutable }
+import scala.collection.mutable.ListBuffer
+import util.Statistics._
+import Flags._
+
+trait Symbols extends api.Symbols { self: SymbolTable =>
+ import definitions._
+
+ protected var ids = 0
+
+ val emptySymbolArray = new Array[Symbol](0)
+
+ def symbolCount = ids // statistics
+
+ protected def nextId() = { ids += 1; ids }
+
+ /** Used for deciding in the IDE whether we can interrupt the compiler */
+ //protected var activeLocks = 0
+
+ /** Used for debugging only */
+ //protected var lockedSyms = collection.immutable.Set[Symbol]()
+
+ /** Used to keep track of the recursion depth on locked symbols */
+ private var recursionTable = immutable.Map.empty[Symbol, Int]
+
+ private var nextexid = 0
+ protected def freshExistentialName(suffix: String) = {
+ nextexid += 1
+ newTypeName("_" + nextexid + suffix)
+ }
+
+ // Set the fields which point companions at one another. Returns the module.
+ def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = {
+ moduleClass.sourceModule = m
+ m setModuleClass moduleClass
+ m
+ }
+
+ /** Create a new free term. Its owner is NoSymbol.
+ */
+ def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTermSymbol =
+ new FreeTermSymbol(name, value, origin) initFlags flags setInfo info
+
+ /** Create a new free type. Its owner is NoSymbol.
+ */
+ def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTypeSymbol =
+ new FreeTypeSymbol(name, value, origin) initFlags flags setInfo info
+
+ /** The original owner of a class. Used by the backend to generate
+ * EnclosingMethod attributes.
+ */
+ val originalOwner = perRunCaches.newMap[Symbol, Symbol]()
+
+ abstract class SymbolContextApiImpl extends SymbolContextApi {
+ this: Symbol =>
+
+ def kind: String = kindString
+ def isExistential: Boolean = this.isExistentiallyBound
+
+ def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match {
+ case n: TermName => newTermSymbol(n, pos, newFlags)
+ case n: TypeName => if (isClass) newClassSymbol(n, pos, newFlags) else newNonClassSymbol(n, pos, newFlags)
+ }
+
+ def thisPrefix: Type = thisType
+ def selfType: Type = typeOfThis
+ def typeSignature: Type = info
+ def typeSignatureIn(site: Type): Type = site memberInfo this
+
+ def asType: Type = tpe
+ def asTypeIn(site: Type): Type = site.memberType(this)
+ def asTypeConstructor: Type = typeConstructor
+ def setInternalFlags(flag: Long): this.type = { setFlag(flag); this }
+ def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this }
+ def getAnnotations: List[AnnotationInfo] = { initialize; annotations }
+ def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this }
+
+ private def lastElemType(ts: Seq[Type]): Type = ts.last.normalize.typeArgs.head
+
+ private def formalTypes(formals: List[Type], nargs: Int): List[Type] = {
+ val formals1 = formals mapConserve {
+ case TypeRef(_, ByNameParamClass, List(arg)) => arg
+ case formal => formal
+ }
+ if (isVarArgTypes(formals1)) {
+ val ft = lastElemType(formals)
+ formals1.init ::: List.fill(nargs - (formals1.length - 1))(ft)
+ } else formals1
+ }
+
+ def resolveOverloaded(pre: Type, targs: Seq[Type], actuals: Seq[Type]): Symbol = {
+ def firstParams(tpe: Type): (List[Symbol], List[Type]) = tpe match {
+ case PolyType(tparams, restpe) =>
+ val (Nil, formals) = firstParams(restpe)
+ (tparams, formals)
+ case MethodType(params, _) =>
+ (Nil, params map (_.tpe))
+ case _ =>
+ (Nil, Nil)
+ }
+ def isApplicable(alt: Symbol, targs: List[Type], actuals: Seq[Type]) = {
+ def isApplicableType(tparams: List[Symbol], tpe: Type): Boolean = {
+ val (tparams, formals) = firstParams(pre memberType alt)
+ val formals1 = formalTypes(formals, actuals.length)
+ val actuals1 =
+ if (isVarArgTypes(actuals)) {
+ if (!isVarArgTypes(formals)) return false
+ actuals.init :+ lastElemType(actuals)
+ } else actuals
+ if (formals1.length != actuals1.length) return false
+
+ if (tparams.isEmpty) return (actuals1 corresponds formals1)(_ <:< _)
+
+ if (targs.length == tparams.length)
+ isApplicableType(List(), tpe.instantiateTypeParams(tparams, targs))
+ else if (targs.nonEmpty)
+ false
+ else {
+ val tvars = tparams map (TypeVar(_))
+ (actuals1 corresponds formals1) { (actual, formal) =>
+ val tp1 = actual.deconst.instantiateTypeParams(tparams, tvars)
+ val pt1 = actual.instantiateTypeParams(tparams, tvars)
+ tp1 <:< pt1
+ } &&
+ solve(tvars, tparams, List.fill(tparams.length)(COVARIANT), upper = false)
+ }
+ }
+ isApplicableType(List(), pre.memberType(alt))
+ }
+ def isAsGood(alt1: Symbol, alt2: Symbol): Boolean = {
+ alt1 == alt2 ||
+ alt2 == NoSymbol || {
+ val (tparams, formals) = firstParams(pre memberType alt1)
+ isApplicable(alt2, tparams map (_.tpe), formals)
+ }
+ }
+ assert(isOverloaded)
+ val applicables = alternatives filter (isApplicable(_, targs.toList, actuals))
+ def winner(alts: List[Symbol]) =
+ ((NoSymbol: Symbol) /: alts)((best, alt) => if (isAsGood(alt, best)) alt else best)
+ val best = winner(applicables)
+ if (best == winner(applicables.reverse)) best else NoSymbol
+ }
+ }
+
+ /** The class for all symbols */
+ abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name)
+ extends SymbolContextApiImpl
+ with HasFlags
+ with Annotatable[Symbol] {
+
+ type AccessBoundaryType = Symbol
+ type AnnotationType = AnnotationInfo
+
+ // TODO - don't allow names to be renamed in this unstructured a fashion.
+ // Rename as little as possible. Enforce invariants on all renames.
+ type TypeOfClonedSymbol >: Null <: Symbol { type NameType = Symbol.this.NameType }
+
+ // Abstract here so TypeSymbol and TermSymbol can have a private[this] field
+ // with the proper specific type.
+ def rawname: NameType
+ def name: NameType
+ def name_=(n: Name): Unit
+ def asNameType(n: Name): NameType
+
+ 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 _rawflags: Long = _
+
+ def rawowner = _rawowner
+ def rawflags = _rawflags
+
+ private var rawpos = initPos
+
+ val id = nextId() // identity displayed when -uniqid
+ //assert(id != 3390, initName)
+
+ private[this] var _validTo: Period = NoPeriod
+
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbol(this)
+
+ def validTo = _validTo
+ def validTo_=(x: Period) { _validTo = x}
+
+ def pos = rawpos
+ def setPos(pos: Position): this.type = { this.rawpos = pos; this }
+ def setName(name: Name): this.type = { this.name = asNameType(name) ; this }
+
+ // Update the surrounding scopes
+ protected[this] def changeNameInOwners(name: Name) {
+ if (owner.isClass) {
+ var ifs = owner.infos
+ while (ifs != null) {
+ ifs.info.decls.rehash(this, name)
+ ifs = ifs.prev
+ }
+ }
+ }
+
+ def rawFlagString(mask: Long): String = calculateFlagString(rawflags & mask)
+ def rawFlagString: String = rawFlagString(flagMask)
+ def debugFlagString: String = flagString(AllFlags)
+
+ /** String representation of symbol's variance */
+ def varianceString: String =
+ if (variance == 1) "+"
+ else if (variance == -1) "-"
+ else ""
+
+ override def flagMask =
+ 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 ""
+
+ 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
+ )
+ )
+
+// ------ creators -------------------------------------------------------------------
+
+ final def newValue(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(name, pos, newFlags)
+ final def newVariable(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(name, pos, MUTABLE | newFlags)
+ final def newValueParameter(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(name, pos, PARAM | newFlags)
+
+ /** Create local dummy for template (owner of local blocks) */
+ final def newLocalDummy(pos: Position): TermSymbol =
+ newTermSymbol(nme.localDummyName(this), pos) setInfo NoType
+ final def newMethod(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
+ createMethodSymbol(name, pos, METHOD | newFlags)
+ final def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
+ createMethodSymbol(name, pos, METHOD | newFlags)
+ final def newLabel(name: TermName, pos: Position = NoPosition): MethodSymbol =
+ newMethod(name, pos, LABEL)
+
+ /** Propagates ConstrFlags (JAVA, specifically) from owner to constructor. */
+ final def newConstructor(pos: Position, newFlags: Long = 0L): MethodSymbol =
+ newMethod(nme.CONSTRUCTOR, pos, getFlag(ConstrFlags) | newFlags)
+
+ /** Static constructor with info set. */
+ def newStaticConstructor(pos: Position): MethodSymbol =
+ newConstructor(pos, STATIC) setInfo UnitClass.tpe
+
+ /** Instance constructor with info set. */
+ def newClassConstructor(pos: Position): MethodSymbol =
+ newConstructor(pos) setInfo MethodType(Nil, this.tpe)
+
+ def newLinkedModule(clazz: Symbol, newFlags: Long = 0L): ModuleSymbol = {
+ 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 | 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, PackageFlags | newFlags)
+ }
+
+ final def newThisSym(name: TermName = nme.this_, pos: Position = NoPosition): TermSymbol =
+ newTermSymbol(name, pos, SYNTHETIC)
+
+ final def newImport(pos: Position): TermSymbol =
+ newTermSymbol(nme.IMPORT, pos)
+
+ final def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
+ newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol]
+
+ final def newModuleAndClassSymbol(name: Name, pos: Position, flags: FlagSet): (ModuleSymbol, ClassSymbol) = {
+ val m = newModuleSymbol(name, pos, flags | MODULE)
+ val c = newModuleClass(name.toTypeName, pos, m getFlag ModuleToClassFlags)
+ connectModuleToClass(m, c)
+ (m, c)
+ }
+
+ final def newPackageSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
+ newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol]
+
+ final def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ newClassSymbol(name, pos, newFlags).asInstanceOf[ModuleClassSymbol]
+
+ 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:
+ * class C[T] {
+ * def m(x: T): T
+ * def m'(): T
+ * }
+ * val v: C[Int]
+ *
+ * Then v.m has symbol TermSymbol(flags = {OVERLOADED},
+ * tpe = OverloadedType(C[Int], List(m, m')))
+ * You recover the type of m doing a
+ *
+ * m.tpe.asSeenFrom(pre, C) (generally, owner of m, which is C here).
+ *
+ * or:
+ *
+ * pre.memberType(m)
+ */
+ final def newOverloaded(pre: Type, alternatives: List[Symbol]): TermSymbol = (
+ newTermSymbol(alternatives.head.name.toTermName, alternatives.head.pos, OVERLOADED)
+ setInfo OverloadedType(pre, alternatives)
+ )
+
+ final def newErrorValue(name: TermName): TermSymbol =
+ newTermSymbol(name, pos, SYNTHETIC | IS_ERROR) setInfo ErrorType
+
+ /** Symbol of a type definition type T = ...
+ */
+ final def newAliasType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol =
+ createAliasTypeSymbol(name, pos, newFlags)
+
+ /** Symbol of an abstract type type T >: ... <: ...
+ */
+ final def newAbstractType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol =
+ createAbstractTypeSymbol(name, pos, DEFERRED | newFlags)
+
+ /** Symbol of a type parameter
+ */
+ final def newTypeParameter(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
+ newAbstractType(name, pos, PARAM | newFlags)
+
+// is defined in SymbolCreations
+// final def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
+// (if ((newFlags & DEFERRED) != 0) new AbstractTypeSymbol(this, pos, name)
+// else new AbstractTypeSymbol(this, pos, name)) setFlag newFlags
+
+ /** Symbol of an existential type T forSome { ... }
+ */
+ final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
+ newAbstractType(name, pos, EXISTENTIAL | newFlags)
+
+ /** Synthetic value parameters when parameter symbols are not available
+ */
+ final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[TermSymbol]] = {
+ var cnt = 0
+ def freshName() = { cnt += 1; nme.syntheticParamName(cnt) }
+ mmap(argtypess)(tp => newValueParameter(freshName(), owner.pos.focus, SYNTHETIC) setInfo tp)
+ }
+
+ def newSyntheticTypeParam(): TypeSymbol = newSyntheticTypeParam("T0", 0L)
+ def newSyntheticTypeParam(name: String, newFlags: Long): TypeSymbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty
+ def newSyntheticTypeParams(num: Int): List[TypeSymbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L))
+
+ /** Create a new existential type skolem with this symbol its owner,
+ * based on the given symbol and origin.
+ */
+ def newExistentialSkolem(basis: Symbol, origin: AnyRef): TypeSkolem = {
+ val skolem = newTypeSkolemSymbol(basis.name.toTypeName, origin, basis.pos, (basis.flags | EXISTENTIAL) & ~PARAM)
+ skolem setInfo (basis.info cloneInfo skolem)
+ }
+
+ // flags set up to maintain TypeSkolem's invariant: origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL)
+ // CASEACCESSOR | SYNTHETIC used to single this symbol out in deskolemizeGADT
+ def newGADTSkolem(name: TypeName, origin: Symbol, info: Type): TypeSkolem =
+ newTypeSkolemSymbol(name, origin, origin.pos, origin.flags & ~(EXISTENTIAL | PARAM) | CASEACCESSOR | SYNTHETIC) setInfo info
+
+ final def freshExistential(suffix: String): TypeSymbol =
+ newExistential(freshExistentialName(suffix), pos)
+
+ /** Synthetic value parameters when parameter symbols are not available.
+ * Calling this method multiple times will re-use the same parameter names.
+ */
+ final def newSyntheticValueParams(argtypes: List[Type]): List[TermSymbol] =
+ newSyntheticValueParamss(List(argtypes)).head
+
+ /** Synthetic value parameter when parameter symbol is not available.
+ * Calling this method multiple times will re-use the same parameter name.
+ */
+ final def newSyntheticValueParam(argtype: Type): Symbol =
+ newSyntheticValueParams(List(argtype)).head
+
+ /** Type skolems are type parameters ''seen from the inside''
+ * Assuming a polymorphic method m[T], its type is a PolyType which has a TypeParameter
+ * with name `T` in its typeParams list. While type checking the parameters, result type and
+ * body of the method, there's a local copy of `T` which is a TypeSkolem.
+ */
+ final def newTypeSkolem: TypeSkolem =
+ owner.newTypeSkolemSymbol(name.toTypeName, this, pos, flags)
+
+ final def newClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
+ newClassSymbol(name, pos, newFlags)
+
+ /** A new class with its info set to a ClassInfoType with given scope and parents. */
+ def newClassWithInfo(name: TypeName, parents: List[Type], scope: Scope, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = {
+ val clazz = newClass(name, pos, newFlags)
+ clazz setInfo ClassInfoType(parents, scope, clazz)
+ }
+ final def newErrorClass(name: TypeName): ClassSymbol =
+ newClassWithInfo(name, Nil, new ErrorScope(this), pos, SYNTHETIC | IS_ERROR)
+
+ final def newModuleClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ newModuleClassSymbol(name, pos, newFlags | MODULE)
+
+ final def newAnonymousFunctionClass(pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
+ newClassSymbol(tpnme.ANON_FUN_NAME, pos, FINAL | SYNTHETIC | newFlags)
+
+ final def newAnonymousFunctionValue(pos: Position, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(nme.ANON_FUN_NAME, pos, SYNTHETIC | newFlags) setInfo NoType
+
+ def newImplClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = {
+ newClassSymbol(name, pos, newFlags | IMPLCLASS)
+ }
+
+ /** Refinement types P { val x: String; type T <: Number }
+ * also have symbols, they are refinementClasses
+ */
+ final def newRefinementClass(pos: Position): RefinementClassSymbol =
+ createRefinementClassSymbol(pos, 0L)
+
+ /** Create a new getter for current symbol (which must be a field)
+ */
+ final def newGetter: MethodSymbol = (
+ owner.newMethod(nme.getterName(name.toTermName), NoPosition, getterFlags(flags))
+ setPrivateWithin privateWithin
+ setInfo MethodType(Nil, tpe)
+ )
+
+ final def newErrorSymbol(name: Name): Symbol = name match {
+ case x: TypeName => newErrorClass(x)
+ case x: TermName => newErrorValue(x)
+ }
+
+ @deprecated("Use the other signature", "2.10.0")
+ def newClass(pos: Position, name: TypeName): Symbol = newClass(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newModuleClass(pos: Position, name: TypeName): Symbol = newModuleClass(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newLabel(pos: Position, name: TermName): MethodSymbol = newLabel(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newValue(pos: Position, name: TermName): TermSymbol = newTermSymbol(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newAliasType(pos: Position, name: TypeName): Symbol = newAliasType(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newAbstractType(pos: Position, name: TypeName): Symbol = newAbstractType(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newExistential(pos: Position, name: TypeName): Symbol = newExistential(name, pos)
+ @deprecated("Use the other signature", "2.10.0")
+ def newMethod(pos: Position, name: TermName): MethodSymbol = newMethod(name, pos)
+
+// ----- locking and unlocking ------------------------------------------------------
+
+ // True if the symbol is unlocked.
+ // True if the symbol is locked but still below the allowed recursion depth.
+ // False otherwise
+ private[scala] def lockOK: Boolean = {
+ ((_rawflags & LOCKED) == 0L) ||
+ ((settings.Yrecursion.value != 0) &&
+ (recursionTable get this match {
+ case Some(n) => (n <= settings.Yrecursion.value)
+ case None => true }))
+ }
+
+ // Lock a symbol, using the handler if the recursion depth becomes too great.
+ private[scala] def lock(handler: => Unit): Boolean = {
+ if ((_rawflags & LOCKED) != 0L) {
+ if (settings.Yrecursion.value != 0) {
+ recursionTable get this match {
+ case Some(n) =>
+ if (n > settings.Yrecursion.value) {
+ handler
+ false
+ } else {
+ recursionTable += (this -> (n + 1))
+ true
+ }
+ case None =>
+ recursionTable += (this -> 1)
+ true
+ }
+ } else { handler; false }
+ } else {
+ _rawflags |= LOCKED
+ true
+// activeLocks += 1
+// lockedSyms += this
+ }
+ }
+
+ // Unlock a symbol
+ private[scala] def unlock() = {
+ if ((_rawflags & LOCKED) != 0L) {
+// activeLocks -= 1
+// lockedSyms -= this
+ _rawflags &= ~LOCKED
+ if (settings.Yrecursion.value != 0)
+ recursionTable -= this
+ }
+ }
+
+// ----- tests ----------------------------------------------------------------------
+
+ 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
+ def isSpecialized = this hasFlag SPECIALIZED
+
+ /** 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 isCaseClass = false
+ def isConcreteClass = false
+ def isImplClass = false // the implementation class of a trait
+ def isJavaInterface = false
+ 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 isExistentialQuantified = false
+ def isExistentialSkolem = false
+ def isExistentiallyBound = false
+ def isGADTSkolem = false
+ def isTypeParameter = false
+ def isTypeParameterOrSkolem = false
+ def isTypeSkolem = false
+ def isTypeMacro = false
+
+ /** Qualities of Terms, always false for TypeSymbols.
+ */
+ def isAccessor = false
+ def isBridge = false
+ def isCapturedVariable = false
+ def isClassConstructor = false
+ def isConstructor = false
+ def isEarlyInitialized = false
+ def isGetter = false
+ def isLocalDummy = false
+ def isMixinConstructor = false
+ def isOverloaded = false
+ def isSetter = false
+ def isSetterParameter = false
+ def isValue = false
+ def isValueParameter = false
+ def isVariable = false
+ override def hasDefault = false
+ def isTermMacro = false
+
+ /** Qualities of MethodSymbols, always false for TypeSymbols
+ * and other TermSymbols.
+ */
+ def isCaseAccessorMethod = false
+ def isLiftedMethod = false
+ def isSourceMethod = false
+ def isVarargsMethod = false
+ override def isLabel = false
+
+ /** Package/package object tests */
+ 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
+ def isRootPackage = false
+ def isRootSymbol = false // RootPackage and RootClass. TODO: also NoSymbol.
+ def isEmptyPackage = false
+ def isEmptyPackageClass = false
+
+ /** Is this symbol an effective root for fullname string?
+ */
+ def isEffectiveRoot = false
+
+ /** 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) && (this ne NoSymbol) && owner.isClass
+
+ /** Does this symbol denote a wrapper created by the repl? */
+ final def isInterpreterWrapper = (
+ (this hasFlag MODULE)
+ && owner.isPackageClass
+ && nme.isReplWrapperName(name)
+ )
+ @inline final def getFlag(mask: Long): Long = flags & mask
+ /** Does symbol have ANY flag in `mask` set? */
+ @inline final def hasFlag(mask: Long): Boolean = (flags & mask) != 0
+ /** Does symbol have ALL the flags in `mask` set? */
+ @inline final def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask
+
+ def setFlag(mask: Long): this.type = { _rawflags |= mask ; this }
+ def resetFlag(mask: Long): this.type = { _rawflags &= ~mask ; this }
+ def resetFlags() { rawflags &= TopLevelCreationFlags }
+
+ /** Default implementation calls the generic string function, which
+ * will print overloaded flags as <flag1/flag2/flag3>. Subclasses
+ * of Symbol refine.
+ */
+ override def resolveOverloadedFlag(flag: Long): String = Flags.flagToString(flag)
+
+ /** 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
+ }
+
+ final def flags: Long = {
+ val fs = _rawflags & phase.flagMask
+ (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
+ }
+ def flags_=(fs: Long) = _rawflags = fs
+ def rawflags_=(x: Long) { _rawflags = x }
+
+ final def hasGetter = isTerm && nme.isLocalName(name)
+
+ final def isInitializedToDefault = !isType && hasAllFlags(DEFAULTINIT | ACCESSOR)
+ final def isStaticModule = isModule && isStatic && !isMethod
+ final def isThisSym = isTerm && owner.thisSym == this
+ final def isError = hasFlag(IS_ERROR)
+ final def isErroneous = isError || isInitialized && tpe.isErroneous
+
+ def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem
+
+ // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor
+ def isClassLocalToConstructor = false
+
+ final def isDerivedValueClass =
+ isClass && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass
+
+ final def isMethodWithExtension =
+ isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR)
+
+ final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
+ final def isDefinedInPackage = effectiveOwner.isPackageClass
+ 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 = owner.skipPackageObject
+
+ /** If this is a package object or its implementing class, its owner: otherwise this.
+ */
+ def skipPackageObject: Symbol = this
+
+ /** If this is a constructor, its owner: otherwise this.
+ */
+ final def skipConstructor: Symbol = if (isConstructor) owner else this
+
+ /** Conditions where we omit the prefix when printing a symbol, to avoid
+ * unpleasantries like Predef.String, $iw.$iw.Foo and <empty>.Bippy.
+ */
+ final def isOmittablePrefix = /*!settings.debug.value &&*/ (
+ UnqualifiedOwners(skipPackageObject)
+ || isEmptyPrefix
+ )
+ def isEmptyPrefix = (
+ isEffectiveRoot // has no prefix for real, <empty> or <root>
+ || isAnonOrRefinementClass // has uninteresting <anon> or <refinement> prefix
+ || nme.isReplWrapperName(name) // has ugly $iw. prefix (doesn't call isInterpreterWrapper due to nesting)
+ )
+ def isFBounded = info match {
+ case TypeBounds(_, _) => info.baseTypeSeq exists (_ contains this)
+ case _ => false
+ }
+
+ /** Is symbol a monomorphic type?
+ * assumption: if a type starts out as monomorphic, it will not acquire
+ * type parameters in later phases.
+ */
+ final def isMonomorphicType =
+ isType && {
+ val info = originalInfo
+ info.isComplete && !info.isHigherKinded
+ }
+
+ def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr)
+ def isSerializable = (
+ info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass)
+ || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated
+ )
+ def hasBridgeAnnotation = hasAnnotation(BridgeClass)
+ def isDeprecated = hasAnnotation(DeprecatedAttr)
+ def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
+ def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1)
+ def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0)
+
+ // !!! when annotation arguments are not literal strings, but any sort of
+ // assembly of strings, there is a fair chance they will turn up here not as
+ // Literal(const) but some arbitrary AST. However nothing in the compiler
+ // prevents someone from writing a @migration annotation with a calculated
+ // string. So this needs attention. For now the fact that migration is
+ // private[scala] ought to provide enough protection.
+ def hasMigrationAnnotation = hasAnnotation(MigrationAnnotationClass)
+ def migrationMessage = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(0) }
+ def migrationVersion = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(1) }
+ def elisionLevel = getAnnotation(ElidableMethodClass) flatMap { _.intArg(0) }
+ def implicitNotFoundMsg = getAnnotation(ImplicitNotFoundClass) flatMap { _.stringArg(0) }
+
+ /** Is this symbol an accessor method for outer? */
+ final def isOuterAccessor = {
+ hasFlag(STABLE | SYNTHETIC) &&
+ originalName == nme.OUTER
+ }
+
+ /** Is this symbol an accessor method for outer? */
+ final def isOuterField = {
+ hasFlag(SYNTHETIC) &&
+ originalName == nme.OUTER_LOCAL
+ }
+
+ /** Does this symbol denote a stable value? */
+ def isStable = false
+
+ /** Does this symbol denote the primary constructor of its enclosing class? */
+ final def isPrimaryConstructor =
+ isConstructor && owner.primaryConstructor == this
+
+ /** Does this symbol denote an auxiliary constructor of its enclosing class? */
+ final def isAuxiliaryConstructor =
+ isConstructor && !isPrimaryConstructor
+
+ /** Is this symbol a synthetic apply or unapply method in a companion object of a case class? */
+ final def isCaseApplyOrUnapply =
+ isMethod && isCase && isSynthetic
+
+ /** Is this symbol a trait which needs an implementation class? */
+ final def needsImplClass = (
+ isTrait
+ && (!isInterface || hasFlag(lateINTERFACE))
+ && !isImplClass
+ )
+
+ /** Is this a symbol which exists only in the implementation class, not in its trait? */
+ final def isImplOnly = isPrivate || (
+ (owner.isTrait || owner.isImplClass) && (
+ hasAllFlags(LIFTED | MODULE | METHOD)
+ || isConstructor
+ || hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE)
+ )
+ )
+ final def isModuleVar = hasFlag(MODULEVAR)
+
+ /** Is this symbol static (i.e. with no outer instance)?
+ * Q: When exactly is a sym marked as STATIC?
+ * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
+ * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6
+ */
+ def isStatic = (this hasFlag STATIC) || owner.isStaticOwner
+
+ /** Is this symbol a static constructor? */
+ final def isStaticConstructor: Boolean =
+ isStaticMember && isClassConstructor
+
+ /** Is this symbol a static member of its class? (i.e. needs to be implemented as a Java static?) */
+ final def isStaticMember: Boolean =
+ hasFlag(STATIC) || owner.isImplClass
+
+ /** Does this symbol denote a class that defines static symbols? */
+ 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 = (
+ (this hasFlag FINAL | PACKAGE)
+ || isModuleOrModuleClass && (owner.isPackageClass || !settings.overrideObjects.value)
+ || isTerm && (
+ isPrivate
+ || isLocal
+ || owner.isClass && owner.isEffectivelyFinal
+ )
+ )
+
+ /** Is this symbol locally defined? I.e. not accessed from outside `this` instance */
+ final def isLocal: Boolean = owner.isTerm
+
+ /** Is this symbol a constant? */
+ final def isConstant: Boolean = isStable && isConstantType(tpe.resultType)
+
+ /** Is this class nested in another class or module (not a package)? */
+ def isNestedClass = false
+
+ /** 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
+ */
+ def isLocalClass = false
+
+ def isStableClass = false
+
+/* code for fixing nested objects
+ override final def isModuleClass: Boolean =
+ super.isModuleClass && !isExpandedModuleClass
+*/
+ /** Is this class or type defined as a structural refinement type?
+ */
+ final def isStructuralRefinement: Boolean =
+ (isClass || isType || isModule) && info.normalize/*.underlying*/.isStructuralRefinement
+
+ /** Is this a term symbol only defined in a refinement (so that it needs
+ * to be accessed by reflection)?
+ */
+ def isOnlyRefinementMember: Boolean =
+ isTerm && // type members are not affected
+ owner.isRefinementClass && // owner must be a refinement class
+ (owner.info decl name) == this && // symbol must be explicitly declared in the refinement (not synthesized from glb)
+ allOverriddenSymbols.isEmpty && // symbol must not override a symbol in a base class
+ !isConstant // symbol must not be a constant. Question: Can we exclude @inline methods as well?
+
+ final def isStructuralRefinementMember = owner.isStructuralRefinement && isPossibleInRefinement && isPublic
+ final def isPossibleInRefinement = !isConstructor && !isOverridingSymbol
+
+ /** Is this symbol a member of class `clazz`? */
+ def isMemberOf(clazz: Symbol) =
+ clazz.info.member(name).alternatives contains this
+
+ /** A a member of class `base` is incomplete if
+ * (1) it is declared deferred or
+ * (2) it is abstract override and its super symbol in `base` is
+ * nonexistent or incomplete.
+ *
+ * @param base ...
+ * @return ...
+ */
+ final def isIncompleteIn(base: Symbol): Boolean =
+ this.isDeferred ||
+ (this hasFlag ABSOVERRIDE) && {
+ val supersym = superSymbol(base)
+ supersym == NoSymbol || supersym.isIncompleteIn(base)
+ }
+
+ // Does not always work if the rawInfo is a SourcefileLoader, see comment
+ // in "def coreClassesFirst" in Global.
+ def exists = !owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType }
+
+ final def isInitialized: Boolean =
+ validTo != NoPeriod
+
+ // [Eugene] todo. needs to be reviewed and [only then] rewritten without explicit returns
+ /** Determines whether this symbol can be loaded by subsequent reflective compilation */
+ final def isLocatable: Boolean = {
+ if (this == NoSymbol) return false
+ if (isRoot || isRootPackage) return true
+
+ if (!owner.isLocatable) return false
+ if (owner.isTerm) return false
+ if (isLocalDummy) return false
+
+ if (isType && isNonClassType) return false
+ if (isRefinementClass) return false
+ return true
+ }
+
+ // [Eugene] is it a good idea to add ``dealias'' to Symbol?
+ /** Expands type aliases */
+ def dealias: Symbol = this
+
+ /** The variance of this symbol as an integer */
+ final def variance: Int =
+ if (isCovariant) 1
+ else if (isContravariant) -1
+ else 0
+
+ /** The sequence number of this parameter symbol among all type
+ * and value parameters of symbol's owner. -1 if symbol does not
+ * appear among the parameters of its owner.
+ */
+ def paramPos: Int = {
+ def searchIn(tpe: Type, base: Int): Int = {
+ def searchList(params: List[Symbol], fallback: Type): Int = {
+ val idx = params indexOf this
+ if (idx >= 0) idx + base
+ else searchIn(fallback, base + params.length)
+ }
+ tpe match {
+ case PolyType(tparams, res) => searchList(tparams, res)
+ case MethodType(params, res) => searchList(params, res)
+ case _ => -1
+ }
+ }
+ searchIn(owner.info, 0)
+ }
+
+// ------ 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
+ // backend).
+ if (!forInteractive) {
+ if (originalOwner contains this) ()
+ else originalOwner(this) = rawowner
+ }
+ assert(isCompilerUniverse, "owner_= is not thread-safe; cannot be run in reflexive code")
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbolOwner(this, owner)
+ _rawowner = owner
+ }
+
+ def ownerChain: List[Symbol] = this :: owner.ownerChain
+ def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain
+
+ // 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
+ def hasNext = current ne NoSymbol
+ def next = { val r = current; current = current.owner; r }
+ }
+
+ /** 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)
+ }
+
+// ------ name attribute --------------------------------------------------------------
+
+ /** If this symbol has an expanded name, its original name, otherwise its name itself.
+ * @see expandName
+ */
+ def originalName: Name = nme.originalName(name)
+
+ /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`.
+ */
+ def encodedName: String = name.toString
+
+ /** The decoded name of the symbol, e.g. `==` instead of `\$eq\$eq`.
+ */
+ def decodedName: String = nme.dropLocalSuffix(name).decode
+
+ private def addModuleSuffix(n: Name): Name =
+ if (needsModuleSuffix) n append nme.MODULE_SUFFIX_STRING else n
+
+ def moduleSuffix: String = (
+ if (needsModuleSuffix) nme.MODULE_SUFFIX_STRING
+ else ""
+ )
+ /** Whether this symbol needs nme.MODULE_SUFFIX_STRING (aka $) appended on the java platform.
+ */
+ def needsModuleSuffix = (
+ hasModuleFlag
+ && !isMethod
+ && !isImplClass
+ && !isJavaDefined
+ )
+ /** These should be moved somewhere like JavaPlatform.
+ */
+ def javaSimpleName: Name = addModuleSuffix(nme.dropLocalSuffix(simpleName))
+ def javaBinaryName: Name = addModuleSuffix(fullNameInternal('/'))
+ def javaClassName: String = addModuleSuffix(fullNameInternal('.')).toString
+
+ /** The encoded full path name of this symbol, where outer names and inner names
+ * are separated by `separator` characters.
+ * Never translates expansions of operators back to operator symbol.
+ * Never adds id.
+ * Drops package objects.
+ */
+ final def fullName(separator: Char): String = fullNameAsName(separator).toString
+
+ /** Doesn't drop package objects, for those situations (e.g. classloading)
+ * where the true path is needed.
+ */
+ private def fullNameInternal(separator: Char): Name = (
+ if (isRoot || isRootPackage || this == NoSymbol) name
+ else if (owner.isEffectiveRoot) name
+ else effectiveOwner.enclClass.fullNameAsName(separator) append separator append name
+ )
+
+ def fullNameAsName(separator: Char): Name = nme.dropLocalSuffix(fullNameInternal(separator))
+
+ /** The encoded full path name of this symbol, where outer names and inner names
+ * are separated by periods.
+ */
+ final def fullName: String = fullName('.')
+
+ /**
+ * Symbol creation implementations.
+ */
+
+ protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol =
+ new AbstractTypeSymbol(this, pos, name) initFlags newFlags
+
+ protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol =
+ new AliasTypeSymbol(this, pos, name) initFlags newFlags
+
+ protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem =
+ new TypeSkolem(this, pos, name, origin) initFlags newFlags
+
+ protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol =
+ new ClassSymbol(this, pos, name) initFlags newFlags
+
+ 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 createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol =
+ new PackageObjectClassSymbol(this, pos) initFlags newFlags
+
+ protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol =
+ new ClassSymbol(this, pos, name) with ImplClassSymbol 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): ModuleSymbol =
+ new ModuleSymbol(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
+
+ 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 (name == tpnme.PACKAGE)
+ createPackageObjectClassSymbol(pos, newFlags)
+ else if ((newFlags & MODULE) != 0)
+ createModuleClassSymbol(name, pos, newFlags)
+ else if ((newFlags & IMPLCLASS) != 0)
+ createImplClassSymbol(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)
+
+ /** The class or term up to which this symbol is accessible,
+ * or RootClass if it is public. As java protected statics are
+ * otherwise completely inaccessible in scala, they are treated
+ * as public.
+ */
+ def accessBoundary(base: Symbol): Symbol = {
+ if (hasFlag(PRIVATE) || isLocal) owner
+ else if (hasAllFlags(PROTECTED | STATIC | JAVA)) enclosingRootClass
+ else if (hasAccessBoundary && !phase.erasedTypes) privateWithin
+ else if (hasFlag(PROTECTED)) base
+ else enclosingRootClass
+ }
+
+ def isLessAccessibleThan(other: Symbol): Boolean = {
+ val tb = this.accessBoundary(owner)
+ val ob1 = other.accessBoundary(owner)
+ val ob2 = ob1.linkedClassOfClass
+ var o = tb
+ while (o != NoSymbol && o != ob1 && o != ob2) {
+ o = o.owner
+ }
+ o != NoSymbol && o != tb
+ }
+
+ /** See comment in HasFlags for how privateWithin combines with flags.
+ */
+ private[this] var _privateWithin: Symbol = _
+ def privateWithin = _privateWithin
+ def privateWithin_=(sym: Symbol) { _privateWithin = sym }
+ def setPrivateWithin(sym: Symbol): this.type = { privateWithin_=(sym) ; this }
+
+ /** Does symbol have a private or protected qualifier set? */
+ final def hasAccessBoundary = (privateWithin != null) && (privateWithin != NoSymbol)
+
+// ------ info and type -------------------------------------------------------------------
+
+ private[Symbols] var infos: TypeHistory = null
+ def originalInfo = {
+ if (infos eq null) null
+ else {
+ var is = infos
+ while (is.prev ne null) { is = is.prev }
+ is.info
+ }
+ }
+
+ /** Get type. The type of a symbol is:
+ * for a type symbol, the type corresponding to the symbol itself,
+ * @M you should use tpeHK for a type symbol with type parameters if
+ * the kind of the type need not be *, as tpe introduces dummy arguments
+ * to generate a type of kind *
+ * for a term symbol, its usual type.
+ * See the tpe/tpeHK overrides in TypeSymbol for more.
+ */
+ def tpe: Type = info
+ def tpeHK: Type = tpe
+
+ /** Get type info associated with symbol at current phase, after
+ * ensuring that symbol is initialized (i.e. type is completed).
+ */
+ def info: Type = try {
+ var cnt = 0
+ while (validTo == NoPeriod) {
+ //if (settings.debug.value) System.out.println("completing " + this);//DEBUG
+ assert(infos ne null, this.name)
+ assert(infos.prev eq null, this.name)
+ val tp = infos.info
+ //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug
+
+ if ((_rawflags & LOCKED) != 0L) { // rolled out once for performance
+ lock {
+ setInfo(ErrorType)
+ throw CyclicReference(this, tp)
+ }
+ } else {
+ _rawflags |= LOCKED
+// activeLocks += 1
+ // lockedSyms += this
+ }
+ val current = phase
+ try {
+ phase = phaseOf(infos.validFrom)
+ tp.complete(this)
+ } finally {
+ unlock()
+ phase = current
+ }
+ cnt += 1
+ // allow for two completions:
+ // one: sourceCompleter to LazyType, two: LazyType to completed type
+ if (cnt == 3) abort("no progress in completing " + this + ":" + tp)
+ }
+ rawInfo
+ }
+ catch {
+ case ex: CyclicReference =>
+ debugwarn("... hit cycle trying to complete " + this.fullLocationString)
+ throw ex
+ }
+
+ def info_=(info: Type) {
+ assert(info ne null)
+ infos = TypeHistory(currentPeriod, info, null)
+ unlock()
+ _validTo = if (info.isComplete) currentPeriod else NoPeriod
+ }
+
+ /** Set initial info. */
+ def setInfo(info: Type): this.type = { info_=(info); this }
+ /** Modifies this symbol's info in place. */
+ def modifyInfo(f: Type => Type): this.type = setInfo(f(info))
+ /** Substitute second list of symbols for first in current info. */
+ def substInfo(syms0: List[Symbol], syms1: List[Symbol]): this.type =
+ if (syms0.isEmpty) this
+ else modifyInfo(_.substSym(syms0, syms1))
+
+ def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info atOwner this)
+
+ /** Set the info and enter this symbol into the owner's scope. */
+ def setInfoAndEnter(info: Type): this.type = {
+ setInfo(info)
+ owner.info.decls enter this
+ this
+ }
+
+ /** Set new info valid from start of this phase. */
+ def updateInfo(info: Type): Symbol = {
+ val pid = phaseId(infos.validFrom)
+ assert(pid <= phase.id, (pid, phase.id))
+ if (pid == phase.id) infos = infos.prev
+ infos = TypeHistory(currentPeriod, info, infos)
+ _validTo = if (info.isComplete) currentPeriod else NoPeriod
+ this
+ }
+
+ def hasRawInfo: Boolean = infos ne null
+ def hasCompleteInfo = hasRawInfo && rawInfo.isComplete
+
+ /** Return info without checking for initialization or completing */
+ def rawInfo: Type = {
+ var infos = this.infos
+ assert(infos != null)
+ val curPeriod = currentPeriod
+ val curPid = phaseId(curPeriod)
+
+ if (validTo != NoPeriod) {
+ // skip any infos that concern later phases
+ while (curPid < phaseId(infos.validFrom) && infos.prev != null)
+ infos = infos.prev
+
+ if (validTo < curPeriod) {
+ // adapt any infos that come from previous runs
+ val current = phase
+ try {
+ infos = adaptInfos(infos)
+
+ //assert(runId(validTo) == currentRunId, name)
+ //assert(runId(infos.validFrom) == currentRunId, name)
+
+ if (validTo < curPeriod) {
+ var itr = infoTransformers.nextFrom(phaseId(validTo))
+ infoTransformers = itr; // caching optimization
+ while (itr.pid != NoPhase.id && itr.pid < current.id) {
+ phase = phaseWithId(itr.pid)
+ val info1 = itr.transform(this, infos.info)
+ if (info1 ne infos.info) {
+ infos = TypeHistory(currentPeriod + 1, info1, infos)
+ this.infos = infos
+ }
+ _validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
+ itr = itr.next
+ }
+ _validTo = if (itr.pid == NoPhase.id) curPeriod
+ else period(currentRunId, itr.pid)
+ }
+ } finally {
+ phase = current
+ }
+ }
+ }
+ infos.info
+ }
+
+ // adapt to new run in fsc.
+ private def adaptInfos(infos: TypeHistory): TypeHistory = {
+ assert(isCompilerUniverse)
+ if (infos == null || runId(infos.validFrom) == currentRunId) {
+ infos
+ } else {
+ val prev1 = adaptInfos(infos.prev)
+ if (prev1 ne infos.prev) prev1
+ else {
+ val pid = phaseId(infos.validFrom)
+
+ _validTo = period(currentRunId, pid)
+ phase = phaseWithId(pid)
+
+ val info1 = (
+ if (isPackageClass) infos.info
+ else adaptToNewRunMap(infos.info)
+ )
+ if (info1 eq infos.info) {
+ infos.validFrom = validTo
+ infos
+ } else {
+ this.infos = TypeHistory(validTo, info1, prev1)
+ this.infos
+ }
+ }
+ }
+ }
+
+ /** Initialize the symbol */
+ final def initialize: this.type = {
+ if (!isInitialized) info
+ this
+ }
+
+ /** Was symbol's type updated during given phase? */
+ final def isUpdatedAt(pid: Phase#Id): Boolean = {
+ assert(isCompilerUniverse)
+ var infos = this.infos
+ while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev
+ infos ne null
+ }
+
+ /** Was symbol's type updated during given phase? */
+ final def hasTypeAt(pid: Phase#Id): Boolean = {
+ assert(isCompilerUniverse)
+ var infos = this.infos
+ while ((infos ne null) && phaseId(infos.validFrom) > pid) infos = infos.prev
+ infos ne null
+ }
+
+ /** Modify term symbol's type so that a raw type C is converted to an existential C[_]
+ *
+ * This is done in checkAccessible and overriding checks in refchecks
+ * We can't do this on class loading because it would result in infinite cycles.
+ */
+ final def cookJavaRawInfo() {
+ if (hasFlag(TRIEDCOOKING)) return else setFlag(TRIEDCOOKING) // only try once...
+ val oldInfo = info
+ doCookJavaRawInfo()
+ }
+
+ protected def doCookJavaRawInfo(): Unit
+
+ /** The type constructor of a symbol is:
+ * For a type symbol, the type corresponding to the symbol itself,
+ * excluding parameters.
+ * Not applicable for term symbols.
+ */
+ def typeConstructor: Type =
+ abort("typeConstructor inapplicable for " + this)
+
+ /** The logic approximately boils down to finding the most recent phase
+ * which immediately follows any of parser, namer, typer, or erasure.
+ * In effect that means this will return one of:
+ *
+ * - packageobjects (follows namer)
+ * - superaccessors (follows typer)
+ * - lazyvals (follows erasure)
+ * - null
+ */
+ private def unsafeTypeParamPhase = {
+ var ph = phase
+ while (ph.prev.keepsTypeParams)
+ ph = ph.prev
+
+ ph
+ }
+ /** The type parameters of this symbol, without ensuring type completion.
+ * assumption: if a type starts out as monomorphic, it will not acquire
+ * type parameters later.
+ */
+ def unsafeTypeParams: List[Symbol] =
+ if (isMonomorphicType) Nil
+ else atPhase(unsafeTypeParamPhase)(rawInfo.typeParams)
+
+ /** The type parameters of this symbol.
+ * assumption: if a type starts out as monomorphic, it will not acquire
+ * type parameters later.
+ */
+ def typeParams: List[Symbol] =
+ if (isMonomorphicType) Nil
+ else {
+ // analogously to the "info" getter, here we allow for two completions:
+ // one: sourceCompleter to LazyType, two: LazyType to completed type
+ if (validTo == NoPeriod)
+ atPhase(phaseOf(infos.validFrom))(rawInfo load this)
+ if (validTo == NoPeriod)
+ atPhase(phaseOf(infos.validFrom))(rawInfo load this)
+
+ rawInfo.typeParams
+ }
+
+ /** The value parameter sections of this symbol.
+ */
+ def paramss: List[List[Symbol]] = info.paramss
+ 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:
+ * {
+ * class C extends P { ... }
+ * new C
+ * }
+ */
+ def classBound: Type = {
+ val tp = refinedType(info.parents, owner)
+ val thistp = tp.typeSymbol.thisType
+ val oldsymbuf = new ListBuffer[Symbol]
+ val newsymbuf = new ListBuffer[Symbol]
+ for (sym <- info.decls) {
+ // todo: what about public references to private symbols?
+ if (sym.isPublic && !sym.isConstructor) {
+ oldsymbuf += sym
+ newsymbuf += (
+ if (sym.isClass)
+ tp.typeSymbol.newAbstractType(sym.name.toTypeName, sym.pos).setInfo(sym.existentialBound)
+ else
+ sym.cloneSymbol(tp.typeSymbol))
+ }
+ }
+ val oldsyms = oldsymbuf.toList
+ val newsyms = newsymbuf.toList
+ for (sym <- newsyms) {
+ addMember(thistp, tp, sym modifyInfo (_ substThisAndSym(this, thistp, oldsyms, newsyms)))
+ }
+ tp
+ }
+
+ /** If we quantify existentially over this symbol,
+ * the bound of the type variable that stands for it
+ * pre: symbol is a term, a class, or an abstract type (no alias type allowed)
+ */
+ def existentialBound: Type
+
+ /** Reset symbol to initial state
+ */
+ def reset(completer: Type): this.type = {
+ resetFlags()
+ infos = null
+ _validTo = NoPeriod
+ //limit = NoPhase.id
+ setInfo(completer)
+ }
+
+ /**
+ * Adds the interface scala.Serializable to the parents of a ClassInfoType.
+ * Note that the tree also has to be updated accordingly.
+ */
+ def makeSerializable() {
+ info match {
+ case ci @ ClassInfoType(_, _, _) =>
+ updateInfo(ci.copy(parents = ci.parents :+ SerializableClass.tpe))
+ case i =>
+ abort("Only ClassInfoTypes can be made serializable: "+ i)
+ }
+ }
+
+// ----- setters implemented in selected subclasses -------------------------------------
+
+ def typeOfThis_=(tp: Type) { throw new UnsupportedOperationException("typeOfThis_= inapplicable for " + this) }
+ def sourceModule_=(sym: Symbol) { throw new UnsupportedOperationException("sourceModule_= inapplicable for " + this) }
+ def addChild(sym: Symbol) { throw new UnsupportedOperationException("addChild inapplicable for " + this) }
+
+// ----- annotations ------------------------------------------------------------
+
+ // null is a marker that they still need to be obtained.
+ private[this] var _annotations: List[AnnotationInfo] = Nil
+
+ def annotationsString = if (annotations.isEmpty) "" else annotations.mkString("(", ", ", ")")
+
+ /** After the typer phase (before, look at the definition's Modifiers), contains
+ * the annotations attached to member a definition (class, method, type, field).
+ */
+ def annotations: List[AnnotationInfo] =
+ _annotations
+
+ def setAnnotations(annots: List[AnnotationInfo]): this.type = {
+ _annotations = annots
+ this
+ }
+
+ def withAnnotations(annots: List[AnnotationInfo]): this.type =
+ setAnnotations(annots ::: annotations)
+
+ def withoutAnnotations: this.type =
+ setAnnotations(Nil)
+
+ def filterAnnotations(p: AnnotationInfo => Boolean): this.type =
+ setAnnotations(annotations filter p)
+
+ def addAnnotation(annot: AnnotationInfo): this.type =
+ setAnnotations(annot :: annotations)
+
+ // Convenience for the overwhelmingly common case
+ def addAnnotation(sym: Symbol, args: Tree*): this.type =
+ addAnnotation(AnnotationInfo(sym.tpe, args.toList, Nil))
+
+// ------ comparisons ----------------------------------------------------------------
+
+ /** A total ordering between symbols that refines the class
+ * inheritance graph (i.e. subclass.isLess(superclass) always holds).
+ * the ordering is given by: (_.isType, -_.baseTypeSeq.length) for type symbols, followed by `id`.
+ */
+ final def isLess(that: Symbol): Boolean = {
+ def baseTypeSeqLength(sym: Symbol) =
+ if (sym.isAbstractType) 1 + sym.info.bounds.hi.baseTypeSeq.length
+ else sym.info.baseTypeSeq.length
+ if (this.isType)
+ (that.isType &&
+ { val diff = baseTypeSeqLength(this) - baseTypeSeqLength(that)
+ diff > 0 || diff == 0 && this.id < that.id })
+ else
+ that.isType || this.id < that.id
+ }
+
+ /** A partial ordering between symbols.
+ * (this isNestedIn that) holds iff this symbol is defined within
+ * a class or method defining that symbol
+ */
+ final def isNestedIn(that: Symbol): Boolean =
+ owner == that || owner != NoSymbol && (owner isNestedIn that)
+
+ /** Is this class symbol a subclass of that symbol,
+ * and is this class symbol also different from Null or Nothing? */
+ def isNonBottomSubClass(that: Symbol): Boolean = false
+
+ /** Overridden in NullClass and NothingClass for custom behavior.
+ */
+ def isSubClass(that: Symbol) = isNonBottomSubClass(that)
+
+ final def isNumericSubClass(that: Symbol): Boolean =
+ definitions.isNumericSubClass(this, that)
+
+ final def isWeakSubClass(that: Symbol) =
+ isSubClass(that) || isNumericSubClass(that)
+
+// ------ overloaded alternatives ------------------------------------------------------
+
+ def alternatives: List[Symbol] =
+ if (isOverloaded) info.asInstanceOf[OverloadedType].alternatives
+ else List(this)
+
+ def filter(cond: Symbol => Boolean): Symbol =
+ if (isOverloaded) {
+ val alts = alternatives
+ val alts1 = alts filter cond
+ if (alts1 eq alts) this
+ else if (alts1.isEmpty) NoSymbol
+ else if (alts1.tail.isEmpty) alts1.head
+ else owner.newOverloaded(info.prefix, alts1)
+ }
+ else if (cond(this)) this
+ else NoSymbol
+
+ def suchThat(cond: Symbol => Boolean): Symbol = {
+ val result = filter(cond)
+ assert(!result.isOverloaded, result.alternatives)
+ result
+ }
+
+ @inline final def map(f: Symbol => Symbol): Symbol = if (this eq NoSymbol) this else f(this)
+
+// ------ cloneing -------------------------------------------------------------------
+
+ /** A clone of this symbol. */
+ final def cloneSymbol: TypeOfClonedSymbol =
+ cloneSymbol(owner)
+
+ /** A clone of this symbol, but with given owner. */
+ final def cloneSymbol(newOwner: Symbol): TypeOfClonedSymbol =
+ cloneSymbol(newOwner, _rawflags)
+ final def cloneSymbol(newOwner: Symbol, newFlags: Long): TypeOfClonedSymbol =
+ cloneSymbol(newOwner, newFlags, null)
+ final def cloneSymbol(newOwner: Symbol, newFlags: Long, newName: Name): TypeOfClonedSymbol = {
+ val clone = cloneSymbolImpl(newOwner, newFlags)
+ ( clone
+ setPrivateWithin privateWithin
+ setInfo (this.info cloneInfo clone)
+ setAnnotations this.annotations
+ )
+ if (clone.thisSym != clone)
+ clone.typeOfThis = (clone.typeOfThis cloneInfo clone)
+
+ if (newName ne null)
+ clone setName asNameType(newName)
+
+ clone
+ }
+
+ /** Internal method to clone a symbol's implementation with the given flags and no info. */
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeOfClonedSymbol
+
+// ------ access to related symbols --------------------------------------------------
+
+ /** The next enclosing class. */
+ def enclClass: Symbol = if (isClass) this else owner.enclClass
+
+ /** The next enclosing method. */
+ def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod
+
+ /** The primary constructor of a class. */
+ def primaryConstructor: Symbol = NoSymbol
+
+ /** The self symbol (a TermSymbol) of a class with explicit self type, or else the
+ * symbol itself (a TypeSymbol).
+ *
+ * WARNING: you're probably better off using typeOfThis, as it's more uniform across classes with and without self variables.
+ *
+ * Example by Paul:
+ * scala> trait Foo1 { }
+ * scala> trait Foo2 { self => }
+ * scala> intp("Foo1").thisSym
+ * res0: $r.intp.global.Symbol = trait Foo1
+ *
+ * scala> intp("Foo2").thisSym
+ * res1: $r.intp.global.Symbol = value self
+ *
+ * Martin says: The reason `thisSym' is `this' is so that thisType can be this.thisSym.tpe.
+ * It's a trick to shave some cycles off.
+ *
+ * Morale: DO: if (clazz.typeOfThis.typeConstructor ne clazz.typeConstructor) ...
+ * DON'T: if (clazz.thisSym ne clazz) ...
+ *
+ */
+ def thisSym: Symbol = this
+
+ /** The type of `this` in a class, or else the type of the symbol itself. */
+ def typeOfThis = thisSym.tpe
+
+ /** If symbol is a class, the type <code>this.type</code> in this class,
+ * otherwise <code>NoPrefix</code>.
+ * We always have: thisType <:< typeOfThis
+ */
+ def thisType: Type = NoPrefix
+
+ /** For a case class, the symbols of the accessor methods, one for each
+ * argument in the first parameter list of the primary constructor.
+ * The empty list for all other classes.
+ */
+ final def caseFieldAccessors: List[Symbol] =
+ (info.decls filter (_.isCaseAccessorMethod)).toList
+
+ final def constrParamAccessors: List[Symbol] =
+ info.decls.toList filter (sym => !sym.isMethod && sym.isParamAccessor)
+
+ /** The symbol accessed by this accessor (getter or setter) function. */
+ final def accessed: Symbol = accessed(owner.info)
+
+ /** The symbol accessed by this accessor function, but with given owner type. */
+ final def accessed(ownerTp: Type): Symbol = {
+ assert(hasAccessorFlag, this)
+ ownerTp decl nme.getterToLocal(getterName.toTermName)
+ }
+
+ /** The module corresponding to this module class (note that this
+ * is not updated when a module is cloned), or NoSymbol if this is not a ModuleClass.
+ */
+ def sourceModule: Symbol = 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
+ * appended to it.
+ */
+ final def implClass: Symbol = owner.info.decl(tpnme.implClassName(name))
+
+ /** The class that is logically an outer class of given `clazz`.
+ * This is the enclosing class, except for classes defined locally to constructors,
+ * where it is the outer class of the enclosing class.
+ */
+ final def outerClass: Symbol =
+ if (owner.isClass) owner
+ else if (isClassLocalToConstructor) owner.enclClass.outerClass
+ else owner.outerClass
+
+ /** For a paramaccessor: a superclass paramaccessor for which this symbol
+ * is an alias, NoSymbol for all others.
+ */
+ def alias: Symbol = NoSymbol
+
+ /** For a lazy value, its lazy accessor. NoSymbol for all others. */
+ def lazyAccessor: Symbol = NoSymbol
+
+ /** If this is a lazy value, the lazy accessor; otherwise this symbol. */
+ def lazyAccessorOrSelf: Symbol = if (isLazy) lazyAccessor else this
+
+ /** If this is an accessor, the accessed symbol. Otherwise, this symbol. */
+ def accessedOrSelf: Symbol = if (hasAccessorFlag) accessed else this
+
+ /** For an outer accessor: The class from which the outer originates.
+ * For all other symbols: NoSymbol
+ */
+ def outerSource: Symbol = NoSymbol
+
+ /** The superclass of this class. */
+ def superClass: Symbol = if (info.parents.isEmpty) NoSymbol else info.parents.head.typeSymbol
+ def parentSymbols: List[Symbol] = info.parents map (_.typeSymbol)
+
+ /** The directly or indirectly inherited mixins of this class
+ * except for mixin classes inherited by the superclass. Mixin classes appear
+ * in linearization order.
+ */
+ def mixinClasses: List[Symbol] = {
+ val sc = superClass
+ ancestors takeWhile (sc ne _)
+ }
+
+ /** All directly or indirectly inherited classes. */
+ def ancestors: List[Symbol] = info.baseClasses drop 1
+
+ @inline final def enclosingSuchThat(p: Symbol => Boolean): Symbol = {
+ var sym = this
+ while (sym != NoSymbol && !p(sym))
+ sym = sym.owner
+ sym
+ }
+
+ /** The package class containing this symbol, or NoSymbol if there
+ * is not one.
+ * TODO: formulate as enclosingSuchThat, after making sure
+ * we can start with current symbol rather than onwner.
+ * TODO: Also harmonize with enclClass, enclMethod etc.
+ */
+ def enclosingPackageClass: Symbol = {
+ var sym = this.owner
+ while (sym != NoSymbol && !sym.isPackageClass)
+ sym = sym.owner
+ sym
+ }
+
+ /** The package class containing this symbol, or NoSymbol if there
+ * is not one. */
+ def enclosingRootClass: Symbol = enclosingSuchThat(_.isRoot)
+
+ /** The package containing this symbol, or NoSymbol if there
+ * is not one. */
+ def enclosingPackage: Symbol = enclosingPackageClass.companionModule
+
+ /** Return the original enclosing method of this symbol. It should return
+ * the same thing as enclMethod when called before lambda lift,
+ * but it preserves the original nesting when called afterwards.
+ *
+ * @note This method is NOT available in the presentation compiler run. The
+ * originalOwner map is not populated for memory considerations (the symbol
+ * may hang on to lazy types and in turn to whole (outdated) compilation units.
+ */
+ def originalEnclosingMethod: Symbol = {
+ assert(!forInteractive, "originalOwner is not kept in presentation compiler runs.")
+ if (isMethod) this
+ else {
+ val owner = originalOwner.getOrElse(this, rawowner)
+ if (isLocalDummy) owner.enclClass.primaryConstructor
+ else owner.originalEnclosingMethod
+ }
+ }
+
+ /** The method or class which logically encloses the current symbol.
+ * If the symbol is defined in the initialization part of a template
+ * this is the template's primary constructor, otherwise it is
+ * the physically enclosing method or class.
+ *
+ * Example 1:
+ *
+ * def f() { val x = { def g() = ...; g() } }
+ *
+ * In this case the owner chain of `g` is `x`, followed by `f` and
+ * `g.logicallyEnclosingMember == f`.
+ *
+ * Example 2:
+ *
+ * class C {
+ * def <init> = { ... }
+ * val x = { def g() = ...; g() } }
+ * }
+ *
+ * In this case the owner chain of `g` is `x`, followed by `C` but
+ * g.logicallyEnclosingMember is the primary constructor symbol `<init>`
+ * (or, for traits: `$init`) of `C`.
+ *
+ */
+ def logicallyEnclosingMember: Symbol =
+ if (isLocalDummy) enclClass.primaryConstructor
+ else if (isMethod || isClass) this
+ else owner.logicallyEnclosingMember
+
+ /** Kept for source compatibility with 2.9. Scala IDE for Eclipse relies on this. */
+ @deprecated("Use enclosingTopLevelClass", "2.10.0")
+ def toplevelClass: Symbol = enclosingTopLevelClass
+
+ /** The top-level class containing this symbol. */
+ def enclosingTopLevelClass: Symbol =
+ if (owner.isPackageClass) {
+ if (isClass) this else moduleClass
+ } else owner.enclosingTopLevelClass
+
+ /** Is this symbol defined in the same scope and compilation unit as `that` symbol? */
+ def isCoDefinedWith(that: Symbol) = {
+ import language.reflectiveCalls
+ (this.rawInfo ne NoType) &&
+ (this.effectiveOwner == that.effectiveOwner) && {
+ !this.effectiveOwner.isPackageClass ||
+ (this.sourceFile eq null) ||
+ (that.sourceFile eq null) ||
+ (this.sourceFile == that.sourceFile) || {
+ // recognize companion object in separate file and fail, else compilation
+ // appears to succeed but highly opaque errors come later: see bug #1286
+ if (this.sourceFile.path != that.sourceFile.path) {
+ // The cheaper check can be wrong: do the expensive normalization
+ // before failing.
+ if (this.sourceFile.canonicalPath != that.sourceFile.canonicalPath)
+ throw InvalidCompanions(this, that)
+ }
+
+ false
+ }
+ }
+ }
+
+ /** The internal representation of classes and objects:
+ *
+ * class Foo is "the class" or sometimes "the plain class"
+ * object Foo is "the module"
+ * class Foo$ is "the module class" (invisible to the user: it implements object Foo)
+ *
+ * class Foo <
+ * ^ ^ (2) \
+ * | | | \
+ * | (5) | (3)
+ * | | | \
+ * (1) v v \
+ * object Foo (4)-> > class Foo$
+ *
+ * (1) companionClass
+ * (2) companionModule
+ * (3) linkedClassOfClass
+ * (4) moduleClass
+ * (5) companionSymbol
+ */
+
+ /** For a module: the class with the same name in the same package.
+ * For all others: NoSymbol
+ * 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.
+ */
+ 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
+ * Note: does not work for modules owned by methods, see Namers.companionModuleOf
+ *
+ * class Foo . companionModule --> object Foo
+ */
+ def companionModule: Symbol = NoSymbol
+
+ /** For a module: its linked class
+ * For a plain class: its linked module or case factory.
+ * Note: does not work for modules owned by methods, see Namers.companionSymbolOf
+ *
+ * class Foo <-- companionSymbol --> object Foo
+ */
+ 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$
+ */
+ def linkedClassOfClass: Symbol = NoSymbol
+
+ /**
+ * Returns the rawInfo of the owner. If the current phase has flat classes,
+ * it first applies all pending type maps to this symbol.
+ *
+ * assume this is the ModuleSymbol for B in the following definition:
+ * package p { class A { object B { val x = 1 } } }
+ *
+ * The owner after flatten is "package p" (see "def owner"). The flatten type map enters
+ * 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.
+ */
+ protected final def flatOwnerInfo: Type = {
+ if (needsFlatClasses)
+ info
+ owner.rawInfo
+ }
+
+ /** If this symbol is an implementation class, its interface, otherwise the symbol itself
+ * The method follows two strategies to determine the interface.
+ * - during or after erasure, it takes the last parent of the implementation class
+ * (which is always the interface, by convention)
+ * - before erasure, it looks up the interface name in the scope of the owner of the class.
+ * This only works for implementation classes owned by other classes or traits.
+ * !!! Why?
+ */
+ def toInterface: Symbol = this
+
+ /** The module class corresponding to this module.
+ */
+ def moduleClass: Symbol = NoSymbol
+
+ /** The non-private symbol whose type matches the type of this symbol
+ * in in given class.
+ *
+ * @param ofclazz The class containing the symbol's definition
+ * @param site The base type from which member types are computed
+ */
+ final def matchingSymbol(ofclazz: Symbol, site: Type): Symbol =
+ ofclazz.info.nonPrivateDecl(name).filter(sym =>
+ !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
+
+ /** The non-private member of `site` whose type and name match the type of this symbol. */
+ final def matchingSymbol(site: Type, admit: Long = 0L): Symbol =
+ site.nonPrivateMemberAdmitting(name, admit).filter(sym =>
+ !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
+
+ /** The symbol, in class `ofclazz`, that is overridden by this symbol.
+ *
+ * @param ofclazz is a base class of this symbol's owner.
+ */
+ final def overriddenSymbol(ofclazz: Symbol): Symbol =
+ if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, owner.thisType)
+
+ /** The symbol overriding this symbol in given subclass `ofclazz`.
+ *
+ * @param ofclazz is a subclass of this symbol's owner
+ */
+ final def overridingSymbol(ofclazz: Symbol): Symbol =
+ if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType)
+
+ /** Returns all symbols overriden by this symbol. */
+ final def allOverriddenSymbols: List[Symbol] =
+ if (!owner.isClass) Nil
+ else owner.ancestors map overriddenSymbol filter (_ != NoSymbol)
+
+ /** Equivalent to allOverriddenSymbols.nonEmpty, but more efficient. */
+ // !!! When if ever will this answer differ from .isOverride?
+ // How/where is the OVERRIDE flag managed, as compared to how checks
+ // based on type membership will evaluate?
+ def isOverridingSymbol = owner.isClass && (
+ owner.ancestors exists (cls => matchingSymbol(cls, owner.thisType) != NoSymbol)
+ )
+ /** Equivalent to allOverriddenSymbols.head (or NoSymbol if no overrides) but more efficient. */
+ def nextOverriddenSymbol: Symbol = {
+ if (owner.isClass) owner.ancestors foreach { base =>
+ val sym = overriddenSymbol(base)
+ if (sym != NoSymbol)
+ return sym
+ }
+ NoSymbol
+ }
+
+ /** Returns all symbols overridden by this symbol, plus all matching symbols
+ * defined in parents of the selftype.
+ */
+ final def extendedOverriddenSymbols: List[Symbol] =
+ if (!owner.isClass) Nil
+ else owner.thisSym.ancestors map overriddenSymbol filter (_ != NoSymbol)
+
+ /** The symbol accessed by a super in the definition of this symbol when
+ * seen from class `base`. This symbol is always concrete.
+ * pre: `this.owner` is in the base class sequence of `base`.
+ */
+ final def superSymbol(base: Symbol): Symbol = {
+ var bcs = base.info.baseClasses.dropWhile(owner != _).tail
+ var sym: Symbol = NoSymbol
+ while (!bcs.isEmpty && sym == NoSymbol) {
+ if (!bcs.head.isImplClass)
+ sym = matchingSymbol(bcs.head, base.thisType).suchThat(!_.isDeferred)
+ bcs = bcs.tail
+ }
+ sym
+ }
+
+ /** The getter of this value or setter definition in class `base`, or NoSymbol if
+ * none exists.
+ */
+ final def getter(base: Symbol): Symbol = base.info.decl(getterName) filter (_.hasAccessorFlag)
+
+ def getterName: TermName = (
+ if (isSetter) nme.setterToGetter(name.toTermName)
+ else if (nme.isLocalName(name)) nme.localToGetter(name.toTermName)
+ else name.toTermName
+ )
+
+ /** The setter of this value or getter definition, or NoSymbol if none exists */
+ final def setter(base: Symbol): Symbol = setter(base, false)
+
+ final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = {
+ var sname = nme.getterToSetter(nme.getterName(name.toTermName))
+ if (hasExpandedName) sname = nme.expandedSetterName(sname, base)
+ base.info.decl(sname) filter (_.hasAccessorFlag)
+ }
+
+ /** Return the accessor method of the first parameter of this class.
+ * or NoSymbol if it does not exist.
+ */
+ def firstParamAccessor: Symbol = NoSymbol
+
+ /** The case module corresponding to this case class
+ * @pre case class is a member of some other class or package
+ */
+ final def caseModule: Symbol = {
+ var modname = name.toTermName
+ if (privateWithin.isClass && !privateWithin.isModuleClass && !hasFlag(EXPANDEDNAME))
+ modname = nme.expandedName(modname, privateWithin)
+ initialize.owner.info.decl(modname).suchThat(_.isModule)
+ }
+
+ /** If this symbol is a type parameter skolem (not an existential skolem!)
+ * its corresponding type parameter, otherwise this */
+ def deSkolemize: Symbol = this
+
+ /** If this symbol is an existential skolem the location (a Tree or null)
+ * where it was unpacked. Resulttype is AnyRef because trees are not visible here. */
+ def unpackLocation: AnyRef = null
+
+ /** Remove private modifier from symbol `sym`s definition. If `sym` is a
+ * is not a constructor nor a static module rename it by expanding its name to avoid name clashes
+ * @param base the fully qualified name of this class will be appended if name expansion is needed
+ */
+ final def makeNotPrivate(base: Symbol) {
+ if (this.isPrivate) {
+ setFlag(notPRIVATE)
+ // Marking these methods final causes problems for proxies which use subclassing. If people
+ // write their code with no usage of final, we probably shouldn't introduce it ourselves
+ // unless we know it is safe. ... Unfortunately if they aren't marked final the inliner
+ // thinks it can't inline them. So once again marking lateFINAL, and in genjvm we no longer
+ // generate ACC_FINAL on "final" methods which are actually lateFINAL.
+ if (isMethod && !isDeferred)
+ setFlag(lateFINAL)
+ if (!isStaticModule && !isClassConstructor) {
+ expandName(base)
+ if (isModule) moduleClass.makeNotPrivate(base)
+ }
+ }
+ }
+
+ /** Remove any access boundary and clear flags PROTECTED | PRIVATE.
+ */
+ def makePublic = this setPrivateWithin NoSymbol resetFlag AccessFlags
+
+ /** The first parameter to the first argument list of this method,
+ * or NoSymbol if inapplicable.
+ */
+ def firstParam = info.params match {
+ case p :: _ => p
+ case _ => NoSymbol
+ }
+/* code for fixing nested objects
+ def expandModuleClassName() {
+ name = newTypeName(name.toString + "$")
+ }
+
+ def isExpandedModuleClass: Boolean = name(name.length - 1) == '$'
+*/
+
+ /** Desire to re-use the field in ClassSymbol which stores the source
+ * file to also store the classfile, but without changing the behavior
+ * of sourceFile (which is expected at least in the IDE only to
+ * return actual source code.) So sourceFile has classfiles filtered out.
+ */
+ private def sourceFileOnly(file: AbstractFileType): AbstractFileType =
+ if ((file eq null) || (file.path endsWith ".class")) null else file
+
+ private def binaryFileOnly(file: AbstractFileType): AbstractFileType =
+ if ((file eq null) || !(file.path endsWith ".class")) null else file
+
+ final def binaryFile: AbstractFileType = binaryFileOnly(associatedFile)
+ final def sourceFile: AbstractFileType = sourceFileOnly(associatedFile)
+
+ /** Overridden in ModuleSymbols to delegate to the module class. */
+ def associatedFile: AbstractFileType = enclosingTopLevelClass.associatedFile
+ def associatedFile_=(f: AbstractFileType) { abort("associatedFile_= inapplicable for " + this) }
+
+ @deprecated("Use associatedFile_= instead", "2.10.0")
+ def sourceFile_=(f: AbstractFileType): Unit = associatedFile_=(f)
+
+ /** If this is a sealed class, its known direct subclasses.
+ * Otherwise, the empty set.
+ */
+ def children: Set[Symbol] = Set()
+
+ /** Recursively assemble all children of this symbol.
+ */
+ def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this
+
+ @inline final def orElse(alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt
+ @inline final def andAlso(f: Symbol => Unit): Symbol = { if (this ne NoSymbol) f(this) ; this }
+
+// ------ toString -------------------------------------------------------------------
+
+ /** A tag which (in the ideal case) uniquely identifies class symbols */
+ final def tag: Int = fullName.##
+
+ /** The simple name of this Symbol */
+ final def simpleName: Name = name
+
+ /** The String used to order otherwise identical sealed symbols.
+ * This uses data which is stable across runs and variable classpaths
+ * (the initial Name) before falling back on id, which varies depending
+ * on exactly when a symbol is loaded.
+ */
+ final def sealedSortName: String = initName + "#" + id
+
+ /** String representation of symbol's definition key word */
+ final def keyString: String =
+ if (isJavaInterface) "interface"
+ else if (isTrait && !isImplClass) "trait"
+ else if (isClass) "class"
+ else if (isType && !isParameter) "type"
+ else if (isVariable) "var"
+ else if (isPackage) "package"
+ else if (isModule) "object"
+ else if (isSourceMethod) "def"
+ else if (isTerm && (!isParameter || isParamAccessor)) "val"
+ else ""
+
+ private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String)
+ private def symbolKind: SymbolKind = {
+ var kind =
+ if (isTermMacro) ("macro method", "macro method", "MAC")
+ else if (isInstanceOf[FreeTermSymbol]) ("free term", "free term", "FTE")
+ else if (isInstanceOf[FreeTypeSymbol]) ("free type", "free type", "FTY")
+ else if (isPackage) ("package", "package", "PK")
+ else if (isPackageClass) ("package class", "package", "PKC")
+ else if (isPackageObject) ("package object", "package", "PKO")
+ else if (isPackageObjectClass) ("package object class", "package", "PKOC")
+ else if (isAnonymousClass) ("anonymous class", "anonymous class", "AC")
+ else if (isRefinementClass) ("refinement class", "", "RC")
+ else if (isModule) ("module", "object", "MOD")
+ else if (isModuleClass) ("module class", "object", "MODC")
+ else if (isGetter) ("getter", if (isSourceMethod) "method" else "value", "GET")
+ else if (isSetter) ("setter", if (isSourceMethod) "method" else "value", "SET")
+ else if (isTerm && isLazy) ("lazy value", "lazy value", "LAZ")
+ else if (isVariable) ("field", "variable", "VAR")
+ else if (isImplClass) ("implementation class", "class", "IMPL")
+ else if (isTrait) ("trait", "trait", "TRT")
+ else if (isClass) ("class", "class", "CLS")
+ else if (isType) ("type", "type", "TPE")
+ else if (isClassConstructor && isPrimaryConstructor) ("primary constructor", "constructor", "PCTOR")
+ else if (isClassConstructor) ("constructor", "constructor", "CTOR")
+ else if (isSourceMethod) ("method", "method", "METH")
+ else if (isTerm) ("value", "value", "VAL")
+ else ("", "", "???")
+ if (isSkolem) kind = (kind._1, kind._2, kind._3 + "#SKO")
+ SymbolKind(kind._1, kind._2, kind._3)
+ }
+
+ /** Accurate string representation of symbols' kind, suitable for developers. */
+ final def accurateKindString: String =
+ symbolKind.accurate
+
+ /** String representation of symbol's kind, suitable for the masses. */
+ private def sanitizedKindString: String =
+ symbolKind.sanitized
+
+ /** String representation of symbol's kind, suitable for the masses. */
+ protected[scala] def abbreviatedKindString: String =
+ symbolKind.abbreviation
+
+ final def kindString: String =
+ if (settings.debug.value) accurateKindString
+ else sanitizedKindString
+
+ /** If the name of the symbol's owner should be used when you care about
+ * seeing an interesting name: in such cases this symbol is e.g. a method
+ * parameter with a synthetic name, a constructor named "this", an object
+ * "package", etc. The kind string, if non-empty, will be phrased relative
+ * to the name of the owner.
+ */
+ def hasMeaninglessName = (
+ isSetterParameter // x$1
+ || isClassConstructor // this
+ || isRefinementClass // <refinement>
+ || (name == nme.PACKAGE) // package
+ )
+
+ /** String representation of symbol's simple name.
+ * If !settings.debug translates expansions of operators back to operator symbol.
+ * E.g. $eq => =.
+ * If settings.uniqid, adds id.
+ * If settings.Yshowsymkinds, adds abbreviated symbol kind.
+ */
+ def nameString: String = (
+ if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + decodedName
+ else if (settings.uniqid.value && !settings.Yshowsymkinds.value) decodedName + "#" + id
+ else if (!settings.uniqid.value && settings.Yshowsymkinds.value) decodedName + "#" + abbreviatedKindString
+ else decodedName + "#" + id + "#" + abbreviatedKindString
+ )
+
+ def fullNameString: String = {
+ def recur(sym: Symbol): String = {
+ if (sym.isRootSymbol || sym == NoSymbol) sym.nameString
+ else if (sym.owner.isEffectiveRoot) sym.nameString
+ else recur(sym.effectiveOwner.enclClass) + "." + sym.nameString
+ }
+
+ recur(this)
+ }
+
+ /** If settings.uniqid is set, the symbol's id, else "" */
+ final def idString = if (settings.uniqid.value) "#"+id else ""
+
+ /** String representation, including symbol's kind e.g., "class Foo", "method Bar".
+ * If hasMeaninglessName is true, uses the owner's name to disambiguate identity.
+ */
+ override def toString: String = compose(
+ kindString,
+ if (hasMeaninglessName) owner.decodedName + idString else nameString
+ )
+
+ /** String representation of location.
+ */
+ def ownsString: String = {
+ val owns = effectiveOwner
+ if (owns.isClass && !owns.isEmptyPrefix) "" + owns else ""
+ }
+
+ /** String representation of location, plus a preposition. Doesn't do much,
+ * for backward compatibility reasons.
+ */
+ def locationString: String = ownsString match {
+ case "" => ""
+ case s => " in " + s
+ }
+ def fullLocationString: String = toString + locationString
+ def signatureString: String = if (hasRawInfo) infoString(rawInfo) else "<_>"
+
+ /** String representation of symbol's definition following its name */
+ final def infoString(tp: Type): String = {
+ def parents = (
+ if (settings.debug.value) parentsString(tp.parents)
+ else briefParentsString(tp.parents)
+ )
+ if (isType) typeParamsString(tp) + (
+ if (isClass) " extends " + parents
+ else if (isAliasType) " = " + tp.resultType
+ else tp.resultType match {
+ case rt @ TypeBounds(_, _) => "" + rt
+ case rt => " <: " + rt
+ }
+ )
+ else if (isModule) "" // avoid "object X of type X.type"
+ else tp match {
+ case PolyType(tparams, res) => typeParamsString(tp) + infoString(res)
+ case NullaryMethodType(res) => infoString(res)
+ case MethodType(params, res) => valueParamsString(tp) + infoString(res)
+ case _ => ": " + tp
+ }
+ }
+
+ def infosString = infos.toString
+ def debugLocationString = fullLocationString + " (flags: " + debugFlagString + ")"
+
+ private def defStringCompose(infoString: String) = compose(
+ flagString,
+ keyString,
+ varianceString + nameString + infoString + flagsExplanationString
+ )
+ /** String representation of symbol's definition. It uses the
+ * symbol's raw info to avoid forcing types.
+ */
+ def defString = defStringCompose(signatureString)
+
+ /** String representation of symbol's definition, using the supplied
+ * info rather than the symbol's.
+ */
+ def defStringSeenAs(info: Type) = defStringCompose(infoString(info))
+
+ /** Concatenate strings separated by spaces */
+ private def compose(ss: String*) = ss filter (_ != "") mkString " "
+
+ def isSingletonExistential =
+ nme.isSingletonName(name) && (info.bounds.hi.typeSymbol isSubClass SingletonClass)
+
+ /** String representation of existentially bound variable */
+ def existentialToString =
+ if (isSingletonExistential && !settings.debug.value)
+ "val " + tpnme.dropSingletonName(name) + ": " + dropSingletonType(info.bounds.hi)
+ else defString
+ }
+ implicit val SymbolTag = ClassTag[Symbol](classOf[Symbol])
+
+ /** A class for term symbols */
+ class TermSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
+ extends Symbol(initOwner, initPos, initName) with TermSymbolApi {
+ private[this] var _referenced: Symbol = NoSymbol
+ privateWithin = NoSymbol
+
+ type TypeOfClonedSymbol = TermSymbol
+
+ private[this] var _rawname: TermName = initName
+ def rawname = _rawname
+ def name = _rawname
+ def name_=(name: Name) {
+ if (name != rawname) {
+ log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name))
+ changeNameInOwners(name)
+ _rawname = name.toTermName
+ }
+ }
+ final def asNameType(n: Name) = n.toTermName
+
+ /** Term symbols with the exception of static parts of Java classes and packages.
+ */
+ override def isValue = !(isModule && hasFlag(PACKAGE | JAVA))
+ override def isVariable = isMutable && !isMethod
+ override def isTermMacro = hasFlag(MACRO)
+
+ // interesting only for lambda lift. Captured variables are accessed from inner lambdas.
+ override def isCapturedVariable = hasAllFlags(MUTABLE | CAPTURED) && !hasFlag(METHOD)
+
+ override def companionSymbol: Symbol = companionClass
+ override def moduleClass = if (isModule) referenced else 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 isSetterParameter = isValueParameter && owner.isSetter
+ override def isAccessor = this hasFlag ACCESSOR
+ override def isGetter = isAccessor && !isSetter
+ override def isSetter = isAccessor && nme.isSetterName(name) // todo: make independent of name, as this can be forged.
+ override def isLocalDummy = nme.isLocalDummyName(name)
+ override def isClassConstructor = name == nme.CONSTRUCTOR
+ override def isMixinConstructor = name == nme.MIXIN_CONSTRUCTOR
+ override def isConstructor = nme.isConstructorName(name)
+
+ override def isPackageObject = isModule && (name == nme.PACKAGE)
+ override def isStable = !isUnstable
+ private def isUnstable = (
+ isMutable
+ || (hasFlag(METHOD | BYNAMEPARAM) && !hasFlag(STABLE))
+ || (tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
+ )
+
+ // The name in comments is what it is being disambiguated from.
+ // TODO - rescue CAPTURED from BYNAMEPARAM so we can see all the names.
+ override def resolveOverloadedFlag(flag: Long) = flag match {
+ case DEFAULTPARAM => "<defaultparam>" // TRAIT
+ case MIXEDIN => "<mixedin>" // EXISTENTIAL
+ case LABEL => "<label>" // CONTRAVARIANT / INCONSTRUCTOR
+ case PRESUPER => "<presuper>" // IMPLCLASS
+ case BYNAMEPARAM => if (this.isValueParameter) "<bynameparam>" else "<captured>" // COVARIANT
+ case _ => super.resolveOverloadedFlag(flag)
+ }
+
+ def referenced: Symbol = _referenced
+ def referenced_=(x: Symbol) { _referenced = x }
+
+ def existentialBound = singletonBounds(this.tpe)
+
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): TermSymbol =
+ owner.newTermSymbol(name, pos, newFlags).copyAttrsFrom(this)
+
+ def copyAttrsFrom(original: TermSymbol): this.type = {
+ referenced = original.referenced
+ this
+ }
+
+ private val validAliasFlags = SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | SPECIALIZED
+
+ override def alias: Symbol =
+ if (hasFlag(validAliasFlags)) initialize.referenced
+ else NoSymbol
+
+ def setAlias(alias: Symbol): TermSymbol = {
+ assert(alias != NoSymbol, this)
+ assert(!alias.isOverloaded, alias)
+ assert(hasFlag(validAliasFlags), this)
+
+ referenced = alias
+ this
+ }
+
+ override def outerSource: Symbol =
+ if (originalName == nme.OUTER) initialize.referenced
+ else NoSymbol
+
+ def setModuleClass(clazz: Symbol): TermSymbol = {
+ assert(isModule, this)
+ referenced = clazz
+ this
+ }
+
+ def setLazyAccessor(sym: Symbol): TermSymbol = {
+ assert(isLazy && (referenced == NoSymbol || referenced == sym), (this, debugFlagString, referenced, sym))
+ referenced = sym
+ this
+ }
+
+ override def lazyAccessor: Symbol = {
+ assert(isLazy, this)
+ 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)
+ // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
+ // object rawToExistentialInJava extends TypeMap {
+ // def apply(tp: Type): Type = tp match {
+ // // any symbol that occurs in a java sig, not just java symbols
+ // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
+ // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
+ // val eparams = typeParamsToExistentials(sym, sym.typeParams)
+ // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
+ // case _ =>
+ // mapOver(tp)
+ // }
+ // }
+ val tpe1 = rawToExistential(sym.tpe)
+ // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1)
+ if (tpe1 ne sym.tpe) {
+ sym.setInfo(tpe1)
+ }
+ }
+
+ if (isJavaDefined)
+ cook(this)
+ else if (isOverloaded)
+ for (sym2 <- alternatives)
+ if (sym2.isJavaDefined)
+ cook(sym2)
+ }
+ }
+ implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol])
+
+ /** A class for module symbols */
+ class ModuleSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
+ extends TermSymbol(initOwner, initPos, initName) with ModuleSymbolApi {
+ private var flatname: TermName = null
+
+ override def associatedFile = moduleClass.associatedFile
+ override def associatedFile_=(f: AbstractFileType) { moduleClass.associatedFile = f }
+
+ override def moduleClass = referenced
+ override def companionClass =
+ flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
+
+ override def owner = (
+ if (!isMethod && needsFlatClasses) rawowner.owner
+ else rawowner
+ )
+ override def name: TermName = (
+ if (!isMethod && needsFlatClasses) {
+ if (flatname eq null)
+ flatname = nme.flattenedName(rawowner.name, rawname)
+
+ flatname
+ }
+ else rawname
+ )
+ }
+ implicit val ModuleSymbolTag = ClassTag[ModuleSymbol](classOf[ModuleSymbol])
+
+ /** A class for method symbols */
+ class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
+ extends TermSymbol(initOwner, initPos, initName) with MethodSymbolApi {
+ private[this] var mtpePeriod = NoPeriod
+ private[this] var mtpePre: Type = _
+ private[this] var mtpeResult: Type = _
+ private[this] var mtpeInfo: Type = _
+
+ override def isLabel = this hasFlag LABEL
+ 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) {
+ if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
+ } else if (isValid(mtpePeriod)) {
+ mtpePeriod = currentPeriod
+ if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
+ }
+ val res = pre.computeMemberType(this)
+ mtpePeriod = currentPeriod
+ mtpePre = pre
+ mtpeInfo = info
+ mtpeResult = res
+ res
+ }
+ }
+ implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol])
+
+ class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends TypeSymbol(initOwner, initPos, initName) {
+ type TypeOfClonedSymbol = TypeSymbol
+ final override def isAliasType = true
+ final override def dealias = info.typeSymbol.dealias
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSymbol =
+ owner.newNonClassSymbol(name, pos, newFlags)
+ }
+
+ class AbstractTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends TypeSymbol(initOwner, initPos, initName) {
+ type TypeOfClonedSymbol = TypeSymbol
+ final override def isAbstractType = true
+ override def existentialBound = this.info
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSymbol =
+ owner.newNonClassSymbol(name, pos, newFlags)
+ }
+
+ /** 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) with TypeSymbolApi {
+ privateWithin = NoSymbol
+ private[this] var _rawname: TypeName = initName
+
+ type TypeOfClonedSymbol >: Null <: TypeSymbol
+ // cloneSymbolImpl still abstract in TypeSymbol.
+
+ def rawname = _rawname
+ def name = _rawname
+ final def asNameType(n: Name) = n.toTypeName
+
+ override def isNonClassType = true
+ override def isTypeMacro = hasFlag(MACRO)
+
+ override def resolveOverloadedFlag(flag: Long) = flag match {
+ case TRAIT => "<trait>" // DEFAULTPARAM
+ case EXISTENTIAL => "<existential>" // MIXEDIN
+ case COVARIANT => "<covariant>" // BYNAMEPARAM / CAPTURED
+ case CONTRAVARIANT => "<contravariant>" // LABEL / INCONSTRUCTOR (overridden again in ClassSymbol)
+ case _ => super.resolveOverloadedFlag(flag)
+ }
+
+ 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)
+
+ // 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) {
+ log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name))
+ changeNameInOwners(name)
+ _rawname = name.toTypeName
+ }
+ }
+
+ 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
+ *
+ * {{{
+ * type T <: Number
+ * }}}
+ *
+ * and tsym is the symbol corresponding to T. Then
+ *
+ * {{{
+ * tsym.info = TypeBounds(Nothing, Number)
+ * tsym.tpe = TypeRef(NoPrefix, T, List())
+ * }}}
+ */
+ override def tpe: Type = {
+ if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor)
+ if (tpePeriod != currentPeriod) {
+ if (isValid(tpePeriod)) {
+ tpePeriod = currentPeriod
+ } else {
+ if (isInitialized) tpePeriod = currentPeriod
+ tpeCache = NoType
+ val targs =
+ if (phase.erasedTypes && this != ArrayClass) List()
+ else unsafeTypeParams map (_.typeConstructor)
+ //@M! use typeConstructor to generate dummy type arguments,
+ // sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
+ // memberType should be used instead, that's why it uses tpeHK and not tpe
+ tpeCache = newTypeRef(targs)
+ }
+ }
+ assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
+ tpeCache
+ }
+
+ /** @M -- tpe vs tpeHK:
+ *
+ * tpe: creates a TypeRef with dummy type arguments and kind *
+ * tpeHK: creates a TypeRef with no type arguments but with type parameters
+ *
+ * If typeParams is nonEmpty, calling tpe may hide errors or
+ * introduce spurious ones. (For example, when deriving a type from
+ * the symbol of a type argument that may be higher-kinded.) As far
+ * as I can tell, it only makes sense to call tpe in conjunction
+ * with a substitution that replaces the generated dummy type
+ * arguments by their actual types.
+ *
+ * TODO: the above conditions desperately need to be enforced by code.
+ */
+ override def tpeHK = typeConstructor // @M! used in memberType
+
+ override def typeConstructor: Type = {
+ if ((tyconCache eq null) || tyconRunId != currentRunId) {
+ tyconCache = newTypeRef(Nil)
+ tyconRunId = currentRunId
+ }
+ assert(tyconCache ne null)
+ tyconCache
+ }
+
+ override def info_=(tp: Type) {
+ tpePeriod = NoPeriod
+ tyconCache = null
+ super.info_=(tp)
+ }
+
+ final override def isNonBottomSubClass(that: Symbol): Boolean = (
+ (this eq that) || this.isError || that.isError ||
+ info.baseTypeIndex(that) >= 0
+ )
+
+ override def reset(completer: Type): this.type = {
+ super.reset(completer)
+ tpePeriod = NoPeriod
+ tyconRunId = NoRunId
+ this
+ }
+
+ /*** example:
+ * public class Test3<T> {}
+ * public class Test1<T extends Test3> {}
+ * info for T in Test1 should be >: Nothing <: Test3[_]
+ */
+ protected def doCookJavaRawInfo() {
+ if (isJavaDefined || owner.isJavaDefined) {
+ val tpe1 = rawToExistential(info)
+ // println("cooking type: "+ this +": "+ info +" to "+ tpe1)
+ if (tpe1 ne info) {
+ setInfo(tpe1)
+ }
+ }
+ }
+
+ incCounter(typeSymbolCount)
+ }
+ implicit val TypeSymbolTag = ClassTag[TypeSymbol](classOf[TypeSymbol])
+
+ /** A class for type parameters viewed from inside their scopes
+ *
+ * @param origin Can be either a tree, or a symbol, or null.
+ * If skolem got created from newTypeSkolem (called in Namers), origin denotes
+ * the type parameter from which the skolem was created. If it got created from
+ * skolemizeExistential, origin is either null or a Tree. If it is a Tree, it indicates
+ * where the skolem was introduced (this is important for knowing when to pack it
+ * again into ab Existential). origin is `null` only in skolemizeExistentials called
+ * from <:< or isAsSpecific, because here its value does not matter.
+ * I believe the following invariant holds:
+ *
+ * origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL)
+ */
+ class TypeSkolem protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef)
+ extends TypeSymbol(initOwner, initPos, initName) {
+ type TypeOfClonedSymbol = TypeSkolem
+ /** The skolemization level in place when the skolem was constructed */
+ val level = skolemizationLevel
+
+ final override def isSkolem = true
+
+ // a type symbol bound by an existential type, for instance the T in
+ // List[T] forSome { type T }
+ override def isExistentialSkolem = this hasFlag EXISTENTIAL
+ override def isGADTSkolem = this hasFlag CASEACCESSOR | SYNTHETIC
+ override def isTypeSkolem = this hasFlag PARAM
+ 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
+ case _ => this
+ }
+
+ /** If type skolem comes from an existential, the tree where it was created */
+ override def unpackLocation = origin
+
+ //@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
+ override def typeParams = info.typeParams
+
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSkolem =
+ owner.newTypeSkolemSymbol(name, origin, pos, newFlags)
+
+ override def nameString: String =
+ if (settings.debug.value) (super.nameString + "&" + level)
+ else super.nameString
+ }
+
+ /** A class for class symbols */
+ class ClassSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends TypeSymbol(initOwner, initPos, initName) with ClassSymbolApi {
+ type TypeOfClonedSymbol = ClassSymbol
+
+ private[this] var flatname: TypeName = _
+ private[this] var _associatedFile: AbstractFileType = _
+ private[this] var thissym: Symbol = this
+
+ private[this] var thisTypeCache: Type = _
+ private[this] var thisTypePeriod = NoPeriod
+
+ override def resolveOverloadedFlag(flag: Long) = flag match {
+ case INCONSTRUCTOR => "<inconstructor>" // INCONSTRUCTOR / CONTRAVARIANT / LABEL
+ case EXISTENTIAL => "<existential>" // EXISTENTIAL / MIXEDIN
+ case IMPLCLASS => "<implclass>" // IMPLCLASS / PRESUPER
+ case _ => super.resolveOverloadedFlag(flag)
+ }
+
+ final override def isNonClassType = false
+ final override def isAbstractType = false
+ final override def isAliasType = false
+
+ override def isAbstractClass = this hasFlag ABSTRACT
+ override def isCaseClass = this hasFlag CASE
+ 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 isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
+ override def isAnonymousClass = name containsName tpnme.ANON_CLASS_NAME
+ override def isConcreteClass = !(this hasFlag ABSTRACT | TRAIT)
+ override def isJavaInterface = hasAllFlags(JAVA | TRAIT)
+ override def isNestedClass = !owner.isPackageClass
+ override def isNumericValueClass = definitions.isNumericValueClass(this)
+ override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE)
+ override def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this)
+
+ // The corresponding interface is the last parent by convention.
+ private def lastParent = if (tpe.parents.isEmpty) NoSymbol else tpe.parents.last.typeSymbol
+ override def toInterface: Symbol = (
+ if (isImplClass) {
+ if (phase.next.erasedTypes) lastParent
+ else owner.info.decl(tpnme.interfaceName(name))
+ }
+ else super.toInterface
+ )
+
+ /** 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 sourceModule = if (isModuleClass) companionModule else NoSymbol
+
+ override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound))
+
+ def primaryConstructorName = if (this hasFlag TRAIT | IMPLCLASS) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR
+
+ override def primaryConstructor = {
+ val c = info decl primaryConstructorName
+ if (c.isOverloaded) c.alternatives.head else c
+ }
+
+ override def associatedFile = if (owner.isPackageClass) _associatedFile else super.associatedFile
+ override def associatedFile_=(f: AbstractFileType) { _associatedFile = f }
+
+ override def reset(completer: Type): this.type = {
+ super.reset(completer)
+ thissym = this
+ this
+ }
+
+ /** the type this.type in this class */
+ override def thisType: Type = {
+ val period = thisTypePeriod
+ if (period != currentPeriod) {
+ thisTypePeriod = currentPeriod
+ if (!isValid(period)) thisTypeCache = ThisType(this)
+ }
+ thisTypeCache
+ }
+
+ override def owner: Symbol =
+ if (needsFlatClasses) rawowner.owner else rawowner
+
+ override def name: TypeName = (
+ if (needsFlatClasses) {
+ if (flatname eq null)
+ flatname = nme.flattenedName(rawowner.name, rawname).toTypeName
+
+ flatname
+ }
+ else rawname
+ )
+
+ /** A symbol carrying the self type of the class as its type */
+ override def thisSym: Symbol = thissym
+
+ /** Sets the self type of the class */
+ override def typeOfThis_=(tp: Type) {
+ thissym = newThisSym(nme.this_, pos).setInfo(tp)
+ }
+
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): ClassSymbol = {
+ val clone = owner.newClassSymbol(name, pos, newFlags)
+ if (thisSym != this) {
+ clone.typeOfThis = typeOfThis
+ clone.thisSym setName thisSym.name
+ }
+ if (_associatedFile ne null)
+ clone.associatedFile = _associatedFile
+
+ clone
+ }
+
+ override def firstParamAccessor =
+ info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse NoSymbol
+
+ private[this] var childSet: Set[Symbol] = Set()
+ override def children = childSet
+ override def addChild(sym: Symbol) { childSet = childSet + sym }
+
+ incCounter(classSymbolCount)
+ }
+ implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol])
+
+ /** A class for module class symbols
+ * Note: Not all module classes are of this type; when unpickled, we get
+ * plain class symbols!
+ */
+ class ModuleClassSymbol protected[Symbols] (owner: Symbol, pos: Position, name: TypeName)
+ extends ClassSymbol(owner, pos, name) {
+ private[this] var module: Symbol = _
+ private[this] var typeOfThisCache: Type = _
+ private[this] var typeOfThisPeriod = NoPeriod
+
+ private var implicitMembersCacheValue: List[Symbol] = Nil
+ private var implicitMembersCacheKey1: Type = NoType
+ private var implicitMembersCacheKey2: ScopeEntry = null
+
+ override def isModuleClass = true
+ override def linkedClassOfClass = companionClass
+
+ /** the self type of an object foo is foo.type, not class<foo>.this.type
+ */
+ override def typeOfThis = {
+ val period = typeOfThisPeriod
+ if (period != currentPeriod) {
+ typeOfThisPeriod = currentPeriod
+ if (!isValid(period))
+ typeOfThisCache = singleType(owner.thisType, sourceModule)
+ }
+ typeOfThisCache
+ }
+
+ def implicitMembers: List[Symbol] = {
+ val tp = info
+ if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) {
+ // Skip a package object class, because the members are also in
+ // the package and we wish to avoid spurious ambiguities as in pos/t3999.
+ if (!isPackageObjectClass) {
+ implicitMembersCacheKey1 = tp
+ implicitMembersCacheKey2 = tp.decls.elems
+ implicitMembersCacheValue = tp.implicitMembers
+ }
+ }
+ implicitMembersCacheValue
+ }
+ // The null check seems to be necessary for the reifier.
+ override def sourceModule = if (module ne null) module else companionModule
+ override def sourceModule_=(module: Symbol) { this.module = module }
+ }
+
+ class PackageObjectClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position)
+ extends ModuleClassSymbol(owner0, pos0, tpnme.PACKAGE) {
+ final override def isPackageObjectClass = true
+ final override def isPackageObjectOrClass = true
+ final override def skipPackageObject = owner
+ final override def setName(name: Name): this.type = {
+ abort("Can't rename a package object to " + name)
+ }
+ }
+
+ trait ImplClassSymbol extends ClassSymbol {
+ override def sourceModule = companionModule
+ // override def isImplClass = true
+ override def typeOfThis = thisSym.tpe // don't use the ModuleClassSymbol typeOfThisCache.
+ }
+
+ class PackageClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position, name0: TypeName)
+ extends ModuleClassSymbol(owner0, pos0, name0) {
+ 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)
+ )
+ }
+
+ trait FreeSymbol extends Symbol {
+ def origin: String
+ }
+ class FreeTermSymbol(name0: TermName, value0: => Any, val origin: String) extends TermSymbol(NoSymbol, NoPosition, name0) with FreeSymbol with FreeTermSymbolApi {
+ def value = value0
+ }
+ implicit val FreeTermSymbolTag = ClassTag[FreeTermSymbol](classOf[FreeTermSymbol])
+
+ class FreeTypeSymbol(name0: TypeName, value0: => Any, val origin: String) extends TypeSkolem(NoSymbol, NoPosition, name0, NoSymbol) with FreeSymbol with FreeTypeSymbolApi {
+ def value = value0
+ }
+ implicit val FreeTypeSymbolTag = ClassTag[FreeTypeSymbol](classOf[FreeTypeSymbol])
+
+ /** An object representing a missing symbol */
+ class NoSymbol protected[Symbols]() extends Symbol(null, NoPosition, nme.NO_NAME) {
+ final type NameType = TermName
+ type TypeOfClonedSymbol = NoSymbol
+
+ def asNameType(n: Name) = n.toTermName
+ def rawname = nme.NO_NAME
+ def name = nme.NO_NAME
+ def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n)
+
+ synchronized {
+ setInfo(NoType)
+ privateWithin = this
+ }
+ override def info_=(info: Type) = {
+ infos = TypeHistory(1, NoType, null)
+ unlock()
+ validTo = currentPeriod
+ }
+ override def flagMask = 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 associatedFile = null
+ override def ownerChain: List[Symbol] = List()
+ override def ownersIterator: Iterator[Symbol] = Iterator.empty
+ override def alternatives: List[Symbol] = List()
+ override def reset(completer: Type): this.type = this
+ override def info: Type = NoType
+ override def existentialBound: Type = NoType
+ override def rawInfo: Type = NoType
+ protected def doCookJavaRawInfo() {}
+ override def accessBoundary(base: Symbol): Symbol = enclosingRootClass
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()")
+ override def originalEnclosingMethod = this
+
+ override def owner: Symbol =
+ abort("no-symbol does not have an owner")
+ override def typeConstructor: Type =
+ abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)")
+ }
+
+ protected def makeNoSymbol: NoSymbol = new NoSymbol
+
+ 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
+ * by substituting the new symbols for the original symbols.
+ *
+ * @param syms the prototypical symbols
+ * @param symFn the function to create new symbols
+ * @return the new list of info-adjusted symbols
+ */
+ def deriveSymbols(syms: List[Symbol], symFn: Symbol => Symbol): List[Symbol] = {
+ val syms1 = syms map symFn
+ syms1 map (_ substInfo (syms, syms1))
+ }
+
+ /** Derives a new Type by first deriving new symbols as in deriveSymbols,
+ * then performing the same oldSyms => newSyms substitution on `tpe` as is
+ * performed on the symbol infos in deriveSymbols.
+ *
+ * @param syms the prototypical symbols
+ * @param symFn the function to create new symbols
+ * @param tpe the prototypical type
+ * @return the new symbol-subsituted type
+ */
+ def deriveType(syms: List[Symbol], symFn: Symbol => Symbol)(tpe: Type): Type = {
+ val syms1 = deriveSymbols(syms, symFn)
+ tpe.substSym(syms, syms1)
+ }
+ /** Derives a new Type by instantiating the given list of symbols as
+ * WildcardTypes.
+ *
+ * @param syms the symbols to replace
+ * @return the new type with WildcardType replacing those syms
+ */
+ def deriveTypeWithWildcards(syms: List[Symbol])(tpe: Type): Type = {
+ if (syms.isEmpty) tpe
+ else tpe.instantiateTypeParams(syms, syms map (_ => WildcardType))
+ }
+ /** Convenience functions which derive symbols by cloning.
+ */
+ def cloneSymbols(syms: List[Symbol]): List[Symbol] =
+ deriveSymbols(syms, _.cloneSymbol)
+ def cloneSymbolsAtOwner(syms: List[Symbol], owner: Symbol): List[Symbol] =
+ deriveSymbols(syms, _ cloneSymbol owner)
+
+ /** Clone symbols and apply the given function to each new symbol's info.
+ *
+ * @param syms the prototypical symbols
+ * @param infoFn the function to apply to the infos
+ * @return the newly created, info-adjusted symbols
+ */
+ def cloneSymbolsAndModify(syms: List[Symbol], infoFn: Type => Type): List[Symbol] =
+ cloneSymbols(syms) map (_ modifyInfo infoFn)
+ def cloneSymbolsAtOwnerAndModify(syms: List[Symbol], owner: Symbol, infoFn: Type => Type): List[Symbol] =
+ cloneSymbolsAtOwner(syms, owner) map (_ modifyInfo infoFn)
+
+ /** Functions which perform the standard clone/substituting on the given symbols and type,
+ * then call the creator function with the new symbols and type as arguments.
+ */
+ def createFromClonedSymbols[T](syms: List[Symbol], tpe: Type)(creator: (List[Symbol], Type) => T): T = {
+ val syms1 = cloneSymbols(syms)
+ creator(syms1, tpe.substSym(syms, syms1))
+ }
+ def createFromClonedSymbolsAtOwner[T](syms: List[Symbol], owner: Symbol, tpe: Type)(creator: (List[Symbol], Type) => T): T = {
+ val syms1 = cloneSymbolsAtOwner(syms, owner)
+ creator(syms1, tpe.substSym(syms, syms1))
+ }
+
+ /** A deep map on a symbol's paramss.
+ */
+ def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f)
+
+ /** An exception for cyclic references of symbol definitions */
+ case class CyclicReference(sym: Symbol, info: Type)
+ extends TypeError("illegal cyclic reference involving " + sym) {
+ if (settings.debug.value) printStackTrace()
+ }
+
+ case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable({
+ import language.reflectiveCalls
+ "Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file:\n" +
+ " Found in " + sym1.sourceFile.canonicalPath + " and " + sym2.sourceFile.canonicalPath
+ }) {
+ override def toString = getMessage
+ }
+
+ /** 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, this)
+
+ override def toString() =
+ "TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")"
+
+ def toList: List[TypeHistory] = this :: ( if (prev eq null) Nil else prev.toList )
+ }
+}