diff options
author | Paul Phillips <paulp@improving.org> | 2012-04-06 15:14:48 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-04-07 17:22:36 -0700 |
commit | b66d390ed4ddc1880db06dd1f1cc1167b6278627 (patch) | |
tree | a6cffd382923e8e21c09499603e343b43097b282 /src/compiler | |
parent | 1a6408c42928211d5d119317cc1aec4eb2481101 (diff) | |
download | scala-b66d390ed4ddc1880db06dd1f1cc1167b6278627.tar.gz scala-b66d390ed4ddc1880db06dd1f1cc1167b6278627.tar.bz2 scala-b66d390ed4ddc1880db06dd1f1cc1167b6278627.zip |
More Symbols and Flags.
Another "three yards and a cloud of dust" in my ongoing
battle against flag uncertainty.
Diffstat (limited to 'src/compiler')
10 files changed, 257 insertions, 187 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 0fa2762c0f..4fd98ad7b3 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -151,6 +151,8 @@ trait Definitions extends reflect.api.StandardDefinitions { // type and term symbols respectively. sealed trait RootSymbol extends WellKnownSymbol { final override def isRootSymbol = true + override def owner = NoSymbol + override def typeOfThis = thisSym.tpe } // This is the package _root_. The actual root cannot be referenced at // the source level, but _root_ is essentially a function => <root>. diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index 48f21721da..05578a2042 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -179,9 +179,6 @@ trait NameManglers { else name.toTermName } - // This isn't needed at the moment since I fixed $class$1 but - // I expect it will be at some point. - // // def anonNumberSuffix(name: Name): Name = { // ("" + name) lastIndexOf '$' match { // case -1 => nme.EMPTY @@ -192,6 +189,18 @@ trait NameManglers { // } // } + // If the name ends with $nn where nn are + // all digits, strip the $ and the digits. + // Otherwise return the argument. + def stripAnonNumberSuffix(name: Name): Name = { + var pos = name.length + while (pos > 0 && name(pos - 1).isDigit) + pos -= 1 + + if (pos <= 0 || pos == name.length || name(pos - 1) != '$') name + else name.subName(0, pos - 1) + } + def stripModuleSuffix(name: Name): Name = ( if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name ) diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index e2c253628c..0cd3616ba9 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -529,6 +529,9 @@ trait StdNames extends NameManglers { self: SymbolTable => def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName = newTermNameCached(base.fullName('$') + separator + name) + def isModuleVarName(name: Name): Boolean = + stripAnonNumberSuffix(name) endsWith MODULE_VAR_SUFFIX + def moduleVarName(name: TermName): TermName = newTermNameCached("" + name + MODULE_VAR_SUFFIX) diff --git a/src/compiler/scala/reflect/internal/SymbolCreations.scala b/src/compiler/scala/reflect/internal/SymbolCreations.scala index 77c4ee27c2..a1163b0f57 100644 --- a/src/compiler/scala/reflect/internal/SymbolCreations.scala +++ b/src/compiler/scala/reflect/internal/SymbolCreations.scala @@ -45,6 +45,8 @@ trait SymbolCreations { protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol + protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol + protected def createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol // Distinguished term categories include methods, modules, packages, package objects, // value parameters, and values (including vals, vars, and lazy vals.) @@ -88,8 +90,12 @@ trait SymbolCreations { 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) } diff --git a/src/compiler/scala/reflect/internal/SymbolFlags.scala b/src/compiler/scala/reflect/internal/SymbolFlags.scala index 0c620f8346..febcec8c7c 100644 --- a/src/compiler/scala/reflect/internal/SymbolFlags.scala +++ b/src/compiler/scala/reflect/internal/SymbolFlags.scala @@ -97,6 +97,11 @@ trait SymbolFlags { } } + /** Flags which should always be present on a particular class of + * Symbol, and never be present on any others. + */ + def AllDistinguishingFlags: Long = METHOD | MODULE | IMPLCLASS + /** A distinguishing flag is one which the mixing class must always * have, and which no other symbol class is allowed to have. */ @@ -125,7 +130,7 @@ trait SymbolFlags { protected def calculateFlagString(basis: Long): String protected def alwaysHasFlags: Long = 0L - protected def neverHasFlags: Long = METHOD | MODULE + protected def neverHasFlags: Long = AllDistinguishingFlags def rawFlagString(mask: Long): String = calculateFlagString(rawflags & mask) def rawFlagString: String = rawFlagString(flagMask) diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index a30714f113..ba1513d12b 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -166,7 +166,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // with the proper specific type. def rawname: NameType def name: NameType - def name_=(n: NameType): Unit + 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 @@ -381,15 +381,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newModuleClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) = newModuleClassSymbol(name, pos, newFlags | MODULE) - final def newAnonymousClass(pos: Position) = - newClassSymbol(tpnme.ANON_CLASS_NAME, pos) - - final def newAnonymousFunctionClass(pos: Position, newFlags: Long = 0L) = + final def newAnonymousFunctionClass(pos: Position = NoPosition, newFlags: Long = 0L) = newClassSymbol(tpnme.ANON_FUN_NAME, pos, FINAL | SYNTHETIC | newFlags) final def newAnonymousFunctionValue(pos: Position, newFlags: Long = 0L) = 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 */ @@ -520,21 +521,23 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 + 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 isExistentialQuantified = false def isGADTSkolem = false def isTypeParameter = false def isTypeParameterOrSkolem = false @@ -542,12 +545,23 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Qualities of Terms, always false for TypeSymbols. */ - override def hasDefault = false - def isBridge = false - def isEarlyInitialized = false - def isModule = false - def isOverloaded = false - def isValueParameter = false + 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 isModule = false + def isOverloaded = false + def isSetter = false + def isSetterParameter = false + def isValue = false + def isValueParameter = false + def isVariable = false + override def hasDefault = false /** Qualities of MethodSymbols, always false for TypeSymbols * and other TermSymbols. @@ -558,13 +572,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isMethod = false def isSourceMethod = false def isVarargsMethod = false + override def isLabel = false /** Package/package object tests */ def isPackage = false def isPackageClass = false def isPackageObject = false def isPackageObjectClass = false - def isPackageObjectOrClass = isPackageObject || isPackageObjectClass def isModuleOrModuleClass = isModule || isModuleClass @@ -625,26 +639,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def flags_=(fs: Long) = _rawflags = fs def rawflags_=(x: Long) { _rawflags = x } - /** Term symbols with the exception of static parts of Java classes and packages. - */ - final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA)) - final def isVariable = isTerm && isMutable && !isMethod - - // interesting only for lambda lift. Captured variables are accessed from inner lambdas. - final def isCapturedVariable = isVariable && hasFlag(CAPTURED) - - final def isGetter = isTerm && hasAccessorFlag && !nme.isSetterName(name) - // todo: make independent of name, as this can be forged. - final def isSetter = isTerm && hasAccessorFlag && nme.isSetterName(name) - def isSetterParameter = isValueParameter && owner.isSetter - final def hasGetter = isTerm && nme.isLocalName(name) final def isInitializedToDefault = !isType && hasAllFlags(DEFAULTINIT | ACCESSOR) - final def isLocalDummy = isTerm && nme.isLocalDummyName(name) - final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR) - final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR) - final def isConstructor = isTerm && nme.isConstructorName(name) final def isStaticModule = isModule && isStatic && !isMethod final def isThisSym = isTerm && owner.thisSym == this final def isError = hasFlag(IS_ERROR) @@ -663,7 +660,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) final def isDefinedInPackage = effectiveOwner.isPackageClass - final def isJavaInterface = isJavaDefined && isTrait final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass /** change name by appending $$<fully-qualified-name-of-class `base`> @@ -681,7 +677,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** If this is a package object or its implementing class, its owner: otherwise this. */ - def skipPackageObject: Symbol = if (this.isPackageObjectOrClass) owner else this + def skipPackageObject: Symbol = this /** If this is a constructor, its owner: otherwise this. */ @@ -752,16 +748,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** Does this symbol denote a stable value? */ - final def isStable = - isTerm && - !isMutable && - (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) && - !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass)) - - // def isVirtualClass = hasFlag(DEFERRED) && isClass - // def isVirtualTrait = hasFlag(DEFERRED) && isTrait - // def isLiftedMethod = hasAllFlags(METHOD | LIFTED) - def isCaseClass = isClass && isCase + def isStable = false /** Does this symbol denote the primary constructor of its enclosing class? */ final def isPrimaryConstructor = @@ -776,20 +763,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => isMethod && isCase && isSynthetic /** Is this symbol a trait which needs an implementation class? */ - final def needsImplClass: Boolean = - isTrait && (!isInterface || hasFlag(lateINTERFACE)) && !isImplClass + 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: Boolean = - hasFlag(PRIVATE) || - (owner.isImplClass || owner.isTrait) && - ((hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE) || isConstructor) || - (hasFlag(LIFTED) && isModule && isMethod)) - - /** Is this symbol a module variable? - * This used to have to test for MUTABLE to distinguish the overloaded - * MODULEVAR/SYNTHETICMETH flag, but now SYNTHETICMETH is gone. - */ + 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)? */ @@ -883,7 +870,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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. @@ -1031,6 +1017,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 @@ -1529,6 +1521,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) if (clone.thisSym != clone) clone.typeOfThis = (clone.typeOfThis cloneInfo clone) + if (newName ne null) clone setName asNameType(newName) @@ -1604,8 +1597,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => * is not updated when a module is cloned), or NoSymbol if this is not a ModuleClass. */ def sourceModule: Symbol = NoSymbol - // if (isModuleClass) companionModule else NoSymbol - // NoSymbol /** The implementation class of a trait. If available it will be the * symbol with the same owner, and the name of this symbol with $class @@ -1830,18 +1821,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * This only works for implementation classes owned by other classes or traits. * !!! Why? */ - final def toInterface: Symbol = - if (isImplClass) { - val result = - if (phase.next.erasedTypes) { - assert(!tpe.parents.isEmpty, this) - tpe.parents.last.typeSymbol - } else { - owner.info.decl(nme.interfaceName(name)) - } - assert(result != NoSymbol, this) - result - } else this + def toInterface: Symbol = this /** The module class corresponding to this module. */ @@ -2222,15 +2202,25 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var _rawname: TermName = initName def rawname = _rawname def name = _rawname - def name_=(name: TermName) { + def name_=(name: Name) { if (name != rawname) { + log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name)) changeNameInOwners(name) - _rawname = name + _rawname = name.toTermName } } final def asNameType(n: Name) = n.toTermName final override def isTerm = true + + /** 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 + + // 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 @@ -2243,7 +2233,22 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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. @@ -2285,7 +2290,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } override def outerSource: Symbol = - if (name endsWith nme.OUTER) initialize.referenced + if (originalName == nme.OUTER) initialize.referenced else NoSymbol def setModuleClass(clazz: Symbol): TermSymbol = { @@ -2399,9 +2404,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var mtpeInfo: Type = _ override def isMethod = true + override def isLabel = this hasFlag LABEL override def isMacro = this hasFlag MACRO override def isVarargsMethod = this hasFlag VARARGS override def isLiftedMethod = this hasFlag LIFTED + // TODO - this seems a strange definition for "isSourceMethod", given that // it does not make any specific effort to exclude synthetics. Figure out what // this method is really for and what logic makes sense. @@ -2487,19 +2494,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def existentialBound: Type = abort("unexpected type: "+this.getClass+ " "+debugLocationString) - // a type symbol bound by an existential type, for instance the T in - // List[T] forSome { type T } - // 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: TypeName) { + def name_=(name: Name) { if (name != rawname) { + log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name)) changeNameInOwners(name) - _rawname = 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) @@ -2618,9 +2622,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 isExistentialSkolem = this hasFlag EXISTENTIAL override def isAbstractType = this hasFlag DEFERRED override def isExistentialQuantified = false @@ -2657,15 +2663,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var thisTypeCache: Type = _ private[this] var thisTypePeriod = NoPeriod - private[this] var typeOfThisCache: Type = _ - private[this] var typeOfThisPeriod = NoPeriod override protected def alwaysHasFlags: Long = 0L override protected def neverHasFlags: Long = 0L override def resolveOverloadedFlag(flag: Long) = flag match { - case INCONSTRUCTOR => "<inconstructor>" // CONTRAVARIANT / LABEL - case EXISTENTIAL => "<existential>" // MIXEDIN + case INCONSTRUCTOR => "<inconstructor>" // INCONSTRUCTOR / CONTRAVARIANT / LABEL + case EXISTENTIAL => "<existential>" // EXISTENTIAL / MIXEDIN + case IMPLCLASS => "<implclass>" // IMPLCLASS / PRESUPER case _ => super.resolveOverloadedFlag(flag) } @@ -2675,24 +2680,32 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 isConcreteClass = !(this hasFlag ABSTRACT | TRAIT) - override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE) - - def isTraitOrImplClass = this hasFlag TRAIT | IMPLCLASS - def isNonImplModuleClass = isModuleClass && !isImplClass - - override def isAnonymousClass = name containsName tpnme.ANON_CLASS_NAME override def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass + override def 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(nme.interfaceName(name)) + } + else super.toInterface + ) + /** Is this class locally defined? * A class is local, if * - it is anonymous, or @@ -2734,9 +2747,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 (isTraitOrImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR + def primaryConstructorName = if (this hasFlag TRAIT | IMPLCLASS) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR override def primaryConstructor = { val c = info decl primaryConstructorName @@ -2763,21 +2778,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => thisTypeCache } - /** the self type of an object foo is foo.type, not class<foo>.this.type - */ - override def typeOfThis: Type = { - if (isNonImplModuleClass && owner != NoSymbol) { - val period = typeOfThisPeriod - if (period != currentPeriod) { - typeOfThisPeriod = currentPeriod - if (!isValid(period)) - typeOfThisCache = singleType(owner.thisType, sourceModule) - } - typeOfThisCache - } - else thisSym.tpe - } - override def owner: Symbol = if (needsFlatClasses) rawowner.owner else rawowner @@ -2808,9 +2808,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => clone } - // Must have this line. - override def sourceModule = if (isModuleClass) companionModule else NoSymbol - override def firstParamAccessor = info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse NoSymbol @@ -2827,9 +2824,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ class ModuleClassSymbol protected[Symbols] (owner: Symbol, pos: Position, name: TypeName) extends ClassSymbol(owner, pos, name) with DistinguishingFlag { + private[this] var module: Symbol = _ + private[this] var typeOfThisCache: Type = _ + private[this] var typeOfThisPeriod = NoPeriod + def distinguishingFlag = MODULE - private var module: Symbol = null private var implicitMembersCacheValue: List[Symbol] = Nil private var implicitMembersCacheKey1: Type = NoType private var implicitMembersCacheKey2: ScopeEntry = null @@ -2837,6 +2837,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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)) { @@ -2850,10 +2862,27 @@ trait Symbols extends api.Symbols { self: SymbolTable => } implicitMembersCacheValue } - override def sourceModule = module + // 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) with DistinguishingFlag { override def distinguishingFlag = super.distinguishingFlag | PACKAGE @@ -2864,7 +2893,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => class RefinementClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position) extends ClassSymbol(owner0, pos0, tpnme.REFINE_CLASS_NAME) { - override def name_=(name: TypeName) { + override def name_=(name: Name) { assert(false, "Cannot set name of RefinementClassSymbol to " + name) super.name_=(name) } @@ -2899,7 +2928,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def asNameType(n: Name) = n.toTermName def rawname = nme.NO_NAME def name = nme.NO_NAME - def name_=(n: TermName) = abort("Cannot set name to " + n) + def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n) synchronized { setInfo(NoType) diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala index 2956bc8a21..5ae4ec15ee 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala @@ -21,10 +21,10 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => trait SynchronizedSymbol extends Symbol { - override def rawowner = synchronized { super.rawowner } override def rawflags = synchronized { super.rawflags } - override def rawflags_=(x: Long) = synchronized { super.rawflags_=(x) } + + override def rawowner = synchronized { super.rawowner } override def owner_=(owner: Symbol) = synchronized { super.owner_=(owner) } override def validTo = synchronized { super.validTo } @@ -74,6 +74,12 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol = new RefinementClassSymbol(this, pos) with SynchronizedClassSymbol initFlags newFlags + override protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol = + new ClassSymbol(this, pos, name) with ImplClassSymbol with SynchronizedClassSymbol initFlags newFlags + + override protected def createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol = + new PackageObjectClassSymbol(this, pos) with SynchronizedClassSymbol initFlags newFlags + override protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags @@ -94,7 +100,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => // ------- subclasses --------------------------------------------------------------------- trait SynchronizedTermSymbol extends TermSymbol with SynchronizedSymbol { - override def name_=(x: TermName) = synchronized { super.name_=(x) } + override def name_=(x: Name) = synchronized { super.name_=(x) } override def rawname = synchronized { super.rawname } override def referenced: Symbol = synchronized { super.referenced } override def referenced_=(x: Symbol) = synchronized { super.referenced_=(x) } @@ -105,7 +111,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => } trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol { - override def name_=(x: TypeName) = synchronized { super.name_=(x) } + override def name_=(x: Name) = synchronized { super.name_=(x) } override def rawname = synchronized { super.rawname } override def typeConstructor: Type = synchronized { super.typeConstructor } override def tpe: Type = synchronized { super.tpe } diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index e981910bdb..97e844f6d8 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -64,61 +64,60 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => def implClassPhase = currentRun.erasurePhase.next - /** Return the implementation class of a trait; create a new one of one does not yet exist */ - def implClass(iface: Symbol): Symbol = { - def implClassFlags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS - - iface.info - - implClassMap.getOrElse(iface, { - atPhase(implClassPhase) { - if (iface.implClass ne NoSymbol) - log("%s.implClass == %s".format(iface, iface.implClass)) - - val implName = nme.implClassName(iface.name) - var impl = if (iface.owner.isClass) iface.owner.info.decl(implName) else NoSymbol - - // !!! Why does forcing the impl's info here lead to a crash? - // See test case pos/trait-force-info.scala for a minimization. - // It crashes like this: - // - // [log lazyvals] trait ContextTrees.implClass == class ContextTrees$class - // error: java.lang.AssertionError: assertion failed: (scala.tools.nsc.typechecker.Contexts$NoContext$,scala.tools.nsc.typechecker.Contexts,NoContext$,trait Contexts in package typechecker) / while parsing (/scala/trunk/build/pack/lib/scala-compiler.jar(scala/tools/nsc/interactive/ContextTrees$class.class),Some(class ContextTrees$class))trait Contexts.NoContext$ linkedModule: <none>List() - - val originalImpl = impl - if (impl != NoSymbol) { + private def newImplClass(iface: Symbol): Symbol = { + val inClass = iface.owner.isClass + val implName = nme.implClassName(iface.name) + val implFlags = (iface.flags & ~(INTERFACE | lateINTERFACE)) | IMPLCLASS + + val impl0 = ( + if (!inClass) NoSymbol + else iface.owner.info.decl(implName) match { + case NoSymbol => NoSymbol + case implSym => // Unlink a pre-existing symbol only if the implementation class is // visible on the compilation classpath. In general this is true under // -optimise and not otherwise, but the classpath can use arbitrary // logic so the classpath must be queried. if (classPath.context.isValidName(implName + ".class")) { - log("unlinking impl class " + impl) - iface.owner.info.decls.unlink(impl) - impl = NoSymbol + log("unlinking impl class " + implSym) + iface.owner.info.decls unlink implSym + NoSymbol } - else log("not unlinking existing " + impl + " as the impl class is not visible on the classpath.") - } - if (impl == NoSymbol) { - impl = iface.cloneSymbolImpl(iface.owner, implClassFlags) setName implName - impl.sourceFile = iface.sourceFile - if (iface.owner.isClass) - iface.owner.info.decls enter impl - } - if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile - impl setPos iface.pos - if (impl.flags != implClassFlags) { - log("!!! Directly setting impl class flags from %s to %s".format(flagsToString(impl.flags), flagsToString(implClassFlags))) - impl.flags = implClassFlags - } - impl setInfo new LazyImplClassType(iface) - implClassMap(iface) = impl - debuglog( - "generating impl class " + impl.debugLocationString + " in " + iface.owner + ( - if (originalImpl == NoSymbol) "" else " (cloned from " + originalImpl.debugLocationString + ")" - ) - ) - impl + else { + log("not unlinking existing " + implSym + " as the impl class is not visible on the classpath.") + implSym + } + } + ) + val impl = impl0 orElse { + val impl = iface.owner.newImplClass(implName, iface.pos, implFlags) + if (iface.thisSym != iface) { + impl.typeOfThis = iface.typeOfThis + impl.thisSym setName iface.thisSym.name } + impl.sourceFile = iface.sourceFile + if (inClass) + iface.owner.info.decls enter impl + + impl + } + if (currentRun compiles iface) + currentRun.symSource(impl) = iface.sourceFile + + implClassMap(iface) = impl + impl setInfo new LazyImplClassType(iface) + } + + /** Return the implementation class of a trait; create a new one of one does not yet exist */ + def implClass(iface: Symbol): Symbol = { + iface.info + + implClassMap.getOrElse(iface, atPhase(implClassPhase) { + log("Creating implClass for " + iface) + if (iface.implClass ne NoSymbol) + log("%s.implClass already exists: %s".format(iface, iface.implClass)) + + newImplClass(iface) }) } @@ -138,22 +137,31 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => * given the decls ifaceDecls of its interface. */ private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = { + log("LazyImplClassType calculating decls for " + implClass) + val decls = newScope - if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) + if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) { + log("Adding mixin constructor to " + implClass) + decls enter ( implClass.newMethod(nme.MIXIN_CONSTRUCTOR, implClass.pos) setInfo MethodType(Nil, UnitClass.tpe) ) + } - for (sym <- ifaceDecls.iterator) { + for (sym <- ifaceDecls) { if (isInterfaceMember(sym)) { if (needsImplMethod(sym)) { - val impl = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED) - if (currentRun.compiles(implClass)) implMethodMap(sym) = impl - decls enter impl + log("Cloning " + sym + " for implementation method in " + implClass) + val clone = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED) + if (currentRun.compiles(implClass)) implMethodMap(sym) = clone + decls enter clone sym setFlag lateDEFERRED } - } else { + else log(sym + " needs no implementation method in " + implClass) + } + else { + log("Destructively modifying owner of %s from %s to %s".format(sym, sym.owner, implClass)) sym.owner = implClass // note: OK to destructively modify the owner here, // because symbol will not be accessible from outside the sourcefile. @@ -161,14 +169,17 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => decls enter sym } } + decls } - override def complete(sym: Symbol) { + override def complete(implSym: Symbol) { + log("LazyImplClassType completing " + implSym) + /** If `tp` refers to a non-interface trait, return a * reference to its implementation class. Otherwise return `tp`. */ - def mixinToImplClass(tp: Type): Type = erasure(sym) { + def mixinToImplClass(tp: Type): Type = erasure(implSym) { tp match { //@MATN: no normalize needed (comes after erasure) case TypeRef(pre, sym, _) if sym.needsImplClass => typeRef(pre, implClass(sym), Nil) @@ -179,15 +190,13 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => def implType(tp: Type): Type = tp match { case ClassInfoType(parents, decls, _) => assert(phase == implClassPhase, tp) - ClassInfoType( - ObjectClass.tpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe, - implDecls(sym, decls), - sym - ) + // Impl class parents: Object first, matching interface last. + val implParents = ObjectClass.tpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe + ClassInfoType(implParents, implDecls(implSym, decls), implSym) case PolyType(_, restpe) => implType(restpe) } - sym setInfo implType(beforeErasure(iface.info)) + implSym setInfo implType(beforeErasure(iface.info)) } override def load(clazz: Symbol) { complete(clazz) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 0c867b9e7e..ecfc2b6084 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -1134,10 +1134,10 @@ abstract class Erasure extends AddInterfaces */ override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree) - log("tree after pretransform: "+tree1) + // log("tree after pretransform: "+tree1) afterErasure { val tree2 = mixinTransformer.transform(tree1) - debuglog("tree after addinterfaces: \n" + tree2) + // debuglog("tree after addinterfaces: \n" + tree2) newTyper(rootContext(unit, tree, true)).typed(tree2) } diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index ac76862094..c8de25b2ea 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -27,6 +27,7 @@ abstract class Flatten extends InfoTransform { scope unlink old scope enter sym + log("lifted " + sym.fullLocationString) old } @@ -36,7 +37,7 @@ abstract class Flatten extends InfoTransform { debuglog("re-enter " + sym.fullLocationString) val old = replaceSymbolInCurrentScope(sym) if (old ne NoSymbol) - debuglog("lifted " + sym.fullLocationString + ", unlinked " + old) + log("unlinked " + old.fullLocationString + " after lifting " + sym) } } private def liftSymbol(sym: Symbol) { |