diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-04-26 23:03:04 -0700 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-04-26 23:03:04 -0700 |
commit | 0c5e2e8f577165ac622a93e0b407f272130f0f37 (patch) | |
tree | 3bd70ef1018327f68bba85e0828ad3cdd1bf1b27 /src | |
parent | b48b83cba5cb672ea56ba67a5076c2e91d115ef4 (diff) | |
parent | a61c9c4700a638915b43c93b1fc6b92b9b69444f (diff) | |
download | scala-0c5e2e8f577165ac622a93e0b407f272130f0f37.tar.gz scala-0c5e2e8f577165ac622a93e0b407f272130f0f37.tar.bz2 scala-0c5e2e8f577165ac622a93e0b407f272130f0f37.zip |
Merge pull request #2457 from paulp/pr/late-method-redux
Documented lateMETHOD flag.
Diffstat (limited to 'src')
7 files changed, 51 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 289508f903..db43e633fc 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -539,7 +539,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 8774390c8c..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 @@ -1037,7 +1037,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { else if (!clazz.isTrait) { // This needs to be a def to avoid sharing trees def accessedRef = accessedReference(sym) - if (sym.hasAccessorFlag && (!sym.isDeferred || sym.hasFlag(lateDEFERRED))) { + if (isConcreteAccessor(sym)) { // add accessor definitions addDefDef(sym, { if (sym.isSetter) { 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 |