From 4ce196d8152f75163edb362fcd21fb37631b7fde Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 5 Apr 2013 16:54:10 +0200 Subject: Made module class names end in '$'. If module classes have the same names as their companion classes there is the latent trap that TypeRefs refer to one or the other. To avoid cross-talk, module classes need to have a different name. Also, some fixes to baseType, isSubClass in SymDenotations. --- src/dotty/tools/dotc/core/NameOps.scala | 21 +++++++++++++++++---- src/dotty/tools/dotc/core/SymDenotations.scala | 13 +++++++++---- src/dotty/tools/dotc/core/Symbols.scala | 6 ++++-- .../tools/dotc/core/pickling/ClassfileParser.scala | 4 ++-- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 5 +++-- 5 files changed, 35 insertions(+), 14 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index 1045d0de9..60ac3fba9 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -5,7 +5,7 @@ import java.security.MessageDigest import Chars.isOperatorPart import scala.annotation.switch import scala.io.Codec -import Names._, StdNames._, Contexts._, Symbols._ +import Names._, StdNames._, Contexts._, Symbols._, Flags._ import Decorators.StringDecorator object NameOps { @@ -60,7 +60,7 @@ object NameOps { def isSetterName = name endsWith SETTER_SUFFIX def isTraitSetterName = isSetterName && (name containsSlice TRAIT_SETTER_SEPARATOR) def isSingletonName = name endsWith SINGLETON_SUFFIX - def isModuleName = name endsWith MODULE_SUFFIX + def isModuleClassName = name endsWith MODULE_SUFFIX def isModuleVarName(name: Name): Boolean = name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX @@ -106,8 +106,14 @@ object NameOps { name } - def stripModuleSuffix: Name = - if (isModuleName) name dropRight MODULE_SUFFIX.length else name + /** If name ends in module class suffix, drop it */ + def stripModuleClassSuffix: Name = + if (isModuleClassName) name dropRight MODULE_SUFFIX.length else name + + /** If flags is a ModuleClass but not a Package, add module class suffix */ + def adjustIfModuleClass(flags: Flags.FlagSet): N = + if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName.asInstanceOf[N] + else name /** The expanded name of `name` relative to this class `base` with given `separator` */ @@ -172,6 +178,13 @@ object NameOps { tpnme.Float -> jtpnme.BoxedFloat, tpnme.Double -> jtpnme.BoxedDouble) + implicit class TypeNameDecorator(val name: TypeName) extends AnyVal { + import nme._ + + /** Convert this name to a module name */ + def moduleClassName = name ++ tpnme.MODULE_SUFFIX + } + implicit class TermNameDecorator(val name: TermName) extends AnyVal { import nme._ diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 661f45f00..209ef8eae 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -483,7 +483,7 @@ object SymDenotations { * NoSymbol if this module does not exist. */ final def companionModule(implicit ctx: Context): Symbol = { - owner.info.decl(name.toTermName) + owner.info.decl(name.stripModuleClassSuffix.toTermName) .suchThat(sym => (sym is Module) && sym.isCoDefinedWith(symbol)) .symbol } @@ -493,7 +493,7 @@ object SymDenotations { * NoSymbol if this class does not exist. */ final def companionClass(implicit ctx: Context): Symbol = - owner.info.decl(name.toTypeName) + owner.info.decl(name.stripModuleClassSuffix.toTypeName) .suchThat(sym => sym.isClass && sym.isCoDefinedWith(symbol)) .symbol @@ -634,6 +634,8 @@ object SymDenotations { // ----- denotation fields and accessors ------------------------------ + if (initFlags is (Module, butNot = Package)) assert(name.isModuleClassName, this) + /** The symbol asserted to have type ClassSymbol */ def classSymbol: ClassSymbol = symbol.asInstanceOf[ClassSymbol] @@ -731,7 +733,9 @@ object SymDenotations { final override def isSubClass(base: Symbol)(implicit ctx: Context) = isNonBottomSubClass(base) || - base.isClass && ((symbol eq defn.NothingClass) || (symbol eq defn.NullClass)) + base.isClass && ( + (symbol eq defn.NothingClass) || + (symbol eq defn.NullClass) && (base ne defn.NothingClass)) private[this] var _memberFingerPrint: FingerPrint = FingerPrint.empty @@ -886,7 +890,8 @@ object SymDenotations { } ctx.debugTraceIndented(s"$tp.baseType($this) ${tp.typeSymbol.fullName} ${this.fullName}") { - if (symbol.isStatic) symbol.typeConstructor + if (symbol.isStatic && tp.typeSymbol.isNonBottomSubClass(symbol)) + symbol.typeConstructor else tp match { case tp: CachedType => if (baseTypeValid != ctx.runId) { diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 739d56d2f..ee53b0368 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -11,7 +11,7 @@ import Decorators._ import Symbols._ import Contexts._ import SymDenotations._, util.Texts._ -import Types._, Annotations._, Positions._, StdNames._, Trees._ +import Types._, Annotations._, Positions._, StdNames._, Trees._, NameOps._ import Denotations.{ Denotation, SingleDenotation, MultiDenotation } import collection.mutable import io.AbstractFile @@ -116,8 +116,10 @@ trait Symbols { this: Context => val base = owner.thisType val module = newNakedSymbol[TermName](coord) val modcls = newNakedClassSymbol(coord, assocFile) + val modclsFlags = clsFlags | ModuleClassCreationFlags + val modclsName = name.toTypeName.adjustIfModuleClass(modclsFlags) val cdenot = SymDenotation( - modcls, owner, name.toTypeName, clsFlags | ModuleClassCreationFlags, + modcls, owner, modclsName, modclsFlags, infoFn(module, modcls), privateWithin) val mdenot = SymDenotation( module, owner, name, modFlags | ModuleCreationFlags, diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 4981a6f4e..ac0e86110 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -684,7 +684,7 @@ class ClassfileParser( innerClasses.get(externalName) match { case Some(entry) => - val outerName = entry.outerName.stripModuleSuffix + val outerName = entry.outerName.stripModuleClassSuffix val owner = classSymbol(outerName) val result = cctx.atPhaseNotLaterThanTyper { implicit ctx => getMember(owner, innerName.toTypeName) @@ -808,7 +808,7 @@ class ClassfileParser( val start = starts(index) if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) val name = getExternalName(in.getChar(start + 1)) - if (name.isModuleName) c = cctx.requiredModule(name.stripModuleSuffix.asTermName) + if (name.isModuleClassName) c = cctx.requiredModule(name.stripModuleClassSuffix.asTermName) else c = classNameToSymbol(name) values(index) = c } diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index c47b3b2d4..bed88e1dd 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -412,9 +412,10 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: // symbols that were pickled with Pickler.writeSymInfo val nameref = readNat() - val name = at(nameref, readName) + val name0 = at(nameref, readName) val owner = readSymbolRef() - val flags = unpickleScalaFlags(readLongNat(), name.isTypeName) + val flags = unpickleScalaFlags(readLongNat(), name0.isTypeName) + val name = name0.adjustIfModuleClass(flags) def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) && !(flags is ModuleClass) def isModuleClassRoot = (name == moduleClassRoot.name) && (owner == moduleClassRoot.owner) && (flags is Module) -- cgit v1.2.3