diff options
7 files changed, 50 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 9603aab338..315bda4c32 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -540,7 +540,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { collectInnerClass(sym) - val hasInternalName = (sym.isClass || (sym.isModule && !sym.isMethod)) + val hasInternalName = sym.isClass || sym.isModuleNotMethod val cachedJN = javaNameCache.getOrElseUpdate(sym, { if (hasInternalName) { sym.javaBinaryName } else { sym.javaSimpleName } diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 1aa5f10738..95a1f50465 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -83,7 +83,7 @@ abstract class ExplicitOuter extends InfoTransform else findOrElse(clazz.info.decls)(_.outerSource == clazz)(NoSymbol) } def newOuterAccessor(clazz: Symbol) = { - val accFlags = SYNTHETIC | ARTIFACT | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 ) + val accFlags = SYNTHETIC | ARTIFACT | STABLE | ( if (clazz.isTrait) DEFERRED else 0 ) val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags) val restpe = if (clazz.isTrait) clazz.outerClass.tpe_* else clazz.outerClass.thisType diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 6baffc4e4f..7fe7947239 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -34,7 +34,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** A member of a trait is implemented statically if its implementation after the * mixin transform is in the static implementation module. To be statically * implemented, a member must be a method that belonged to the trait's implementation class - * before (e.g. it is not abstract). Not statically implemented are + * before (i.e. it is not abstract). Not statically implemented are * - non-private modules: these are implemented directly in the mixin composition class * (private modules, on the other hand, are implemented statically, but their * module variable is not. all such private modules are lifted, because diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index c462b8f8ef..5ef54bfad1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -59,7 +59,22 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans override def changesBaseClasses = false override def transformInfo(sym: Symbol, tp: Type): Type = { - if (sym.isModule && !sym.isStatic) sym setFlag (lateMETHOD | STABLE) + // !!! This is a sketchy way to do things. + // It would be better to replace the module symbol with a method symbol + // rather than creating this module/method hybrid which must be special + // cased all over the place. Look for the call sites which use(d) some + // variation of "isMethod && !isModule", which to an observer looks like + // a nonsensical condition. (It is now "isModuleNotMethod".) + if (sym.isModule && !sym.isStatic) { + sym setFlag lateMETHOD | STABLE + // Note that this as far as we can see it works equally well + // to set the METHOD flag here and dump lateMETHOD, but it does + // mean that under separate compilation the typer will see + // modules as methods (albeit stable ones with singleton types.) + // So for now lateMETHOD lives while we try to convince ourselves + // we can live without it or deliver that info some other way. + log(s"Stabilizing module method for ${sym.fullLocationString}") + } super.transformInfo(sym, tp) } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index e22dc73b53..75aa4c46e2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -64,8 +64,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT debuglog(s"add super acc ${sym.fullLocationString} to $clazz") val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE | ARTIFACT) setAlias sym val tpe = clazz.thisType memberType sym match { - case t if sym.isModule && !sym.isMethod => NullaryMethodType(t) - case t => t + case t if sym.isModuleNotMethod => NullaryMethodType(t) + case t => t } acc setInfoAndEnter (tpe cloneInfo acc) // Diagnostic for SI-7091 diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6e26b12226..95a9cea066 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -599,7 +599,7 @@ trait Typers extends Adaptations with Tags { if (sym.isValue) { val tree1 = checkStable(tree) // A module reference in a pattern has type Foo.type, not "object Foo" - if (sym.isModule && !sym.isMethod) tree1 setType singleType(pre, sym) + if (sym.isModuleNotMethod) tree1 setType singleType(pre, sym) else tree1 } else fail() @@ -607,7 +607,7 @@ trait Typers extends Adaptations with Tags { fail() } else { if (sym.isStable && pre.isStable && !isByNameParamType(tree.tpe) && - (isStableContext(tree, mode, pt) || sym.isModule && !sym.isMethod)) + (isStableContext(tree, mode, pt) || sym.isModuleNotMethod)) tree.setType(singleType(pre, sym)) // To fully benefit from special casing the return type of // getClass, we have to catch it immediately so expressions diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index a87d002f25..7465a2e7ab 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -659,8 +659,29 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def hasGetter = isTerm && nme.isLocalName(name) + /** A little explanation for this confusing situation. + * Nested modules which have no static owner when ModuleDefs + * are eliminated (refchecks) are given the lateMETHOD flag, + * which makes them appear as methods after refchecks. + * Here's an example where one can see all four of FF FT TF TT + * for (isStatic, isMethod) at various phases. + * + * trait A1 { case class Quux() } + * object A2 extends A1 { object Flax } + * // -- namer object Quux in trait A1 + * // -M flatten object Quux in trait A1 + * // S- flatten object Flax in object A2 + * // -M posterasure object Quux in trait A1 + * // -M jvm object Quux in trait A1 + * // SM jvm object Quux in object A2 + * + * So "isModuleNotMethod" exists not for its achievement in + * brevity, but to encapsulate the relevant condition. + */ + def isModuleNotMethod = isModule && !isMethod + def isStaticModule = isModuleNotMethod && isStatic + 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 @@ -1110,12 +1131,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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) + // Package before Module, Module before Method, or we might grab the wrong guy. + if ((newFlags & PACKAGE) != 0) createPackageSymbol(name, pos, newFlags | PackageFlags) else if ((newFlags & MODULE) != 0) createModuleSymbol(name, pos, newFlags) + else if ((newFlags & METHOD) != 0) + createMethodSymbol(name, pos, newFlags) else if ((newFlags & PARAM) != 0) createValueParameterSymbol(name, pos, newFlags) else @@ -3027,8 +3049,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * returned, otherwise, `NoSymbol` is returned. */ protected final def companionModule0: Symbol = - flatOwnerInfo.decl(name.toTermName).suchThat( - sym => sym.isModule && (sym isCoDefinedWith this) && !sym.isMethod) + flatOwnerInfo.decl(name.toTermName).suchThat(sym => sym.isModuleNotMethod && (sym isCoDefinedWith this)) override def companionModule = companionModule0 override def companionSymbol = companionModule0 |