diff options
Diffstat (limited to 'src')
23 files changed, 138 insertions, 84 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index e1a3e732b0..00d2c232a0 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -765,8 +765,8 @@ trait Definitions extends reflect.api.StandardDefinitions { } def flatNameString(sym: Symbol, separator: Char): String = if (sym == NoSymbol) "" // be more resistant to error conditions, e.g. neg/t3222.scala - else if (sym.owner.isPackageClass) sym.fullName('.') + (if (sym.isModuleClass) "$" else "") - else flatNameString(sym.owner, separator) + "$" + sym.simpleName; + else if (sym.owner.isPackageClass) sym.javaClassName + else flatNameString(sym.owner, separator) + nme.NAME_JOIN_STRING + sym.simpleName def signature1(etp: Type): String = { if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.normalize.typeArgs.head)) else if (isValueClass(etp.typeSymbol)) abbrvTag(etp.typeSymbol).toString() diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index 571b2ba248..c09397e2c2 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -20,7 +20,10 @@ trait NameManglers { trait NameManglingCommon { self: CommonNames => - def flattenedName(segments: Name*): NameType = compactedString(segments mkString "$") + val MODULE_SUFFIX_STRING = NameTransformer.MODULE_SUFFIX_STRING + val NAME_JOIN_STRING = NameTransformer.NAME_JOIN_STRING + + def flattenedName(segments: Name*): NameType = compactedString(segments mkString NAME_JOIN_STRING) /** * COMPACTIFY @@ -66,12 +69,12 @@ trait NameManglers { self: nme.type => val IMPL_CLASS_SUFFIX = "$class" - val SINGLETON_SUFFIX = ".type" val LOCALDUMMY_PREFIX = "<local " // owner of local blocks val PROTECTED_PREFIX = "protected$" val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set" val SELECTOR_DUMMY = "<unapply-selector>" val SETTER_SUFFIX = encode("_=") + val SINGLETON_SUFFIX = ".type" val SUPER_PREFIX_STRING = "super$" val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$" @@ -87,6 +90,7 @@ trait NameManglers { def isSetterName(name: Name) = name endsWith SETTER_SUFFIX def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING) def isSingletonName(name: Name) = name endsWith SINGLETON_SUFFIX + def isModuleName(name: Name) = name endsWith MODULE_SUFFIX_STRING def isOpAssignmentName(name: Name) = name match { case raw.NE | raw.LE | raw.GE | EMPTY => false @@ -155,6 +159,13 @@ trait NameManglers { else name } + def stripModuleSuffix(name: Name): Name = ( + if (isModuleName(name)) name stripEnd MODULE_SUFFIX_STRING else name + ) + + /** Note that for performance reasons, stripEnd does not verify that the + * suffix is actually the suffix specified. + */ def dropSingletonName(name: Name): TypeName = name stripEnd SINGLETON_SUFFIX toTypeName def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index 43fe89ed63..4947334c1e 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -92,7 +92,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy val ANON_FUN_NAME: NameType = "$anonfun" val EMPTY_PACKAGE_NAME: NameType = "<empty>" val IMPORT: NameType = "<import>" - val MODULE_SUFFIX: NameType = "$module" + val MODULE_VAR_SUFFIX: NameType = "$module" val ROOT: NameType = "<root>" // value types are all used as terms as well @@ -172,7 +172,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy val FAKE_LOCAL_THIS: NameType = "this$" val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something? val MIXIN_CONSTRUCTOR: NameType = "$init$" - val MODULE_INSTANCE_FIELD: NameType = "MODULE$" + val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" val OUTER: NameType = "$outer" val OUTER_LOCAL: NameType = "$outer " // note the space val SELF: NameType = "$this" @@ -374,7 +374,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName = newTermName(base.fullName('$') + separator + name) - def moduleVarName(name: TermName): TermName = newTermName("" + name + MODULE_SUFFIX) + def moduleVarName(name: TermName): TermName = newTermName("" + name + MODULE_VAR_SUFFIX) val EXPAND_SEPARATOR_STRING = "$$" val LOCAL_SUFFIX_STRING = " " diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index f9afd164f5..91f052af6c 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -620,6 +620,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def ownerChain: List[Symbol] = this :: owner.ownerChain + def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain + def enclClassChain: List[Symbol] = { if (this eq NoSymbol) Nil else if (isClass && !isPackageClass) this :: owner.enclClassChain @@ -665,7 +667,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def originalName = nme.originalName(name) - /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`. + /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`. */ def encodedName: String = name.toString @@ -673,6 +675,17 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def decodedName: String = stripLocalSuffix(NameTransformer.decode(encodedName)) + def moduleSuffix: String = ( + if (hasModuleFlag && !isMethod && !isImplClass && !isJavaDefined) nme.MODULE_SUFFIX_STRING + else "" + ) + + /** These should be moved somewhere like JavaPlatform. + */ + def javaSimpleName = stripLocalSuffix("" + simpleName) + moduleSuffix + def javaBinaryName = fullName('/') + moduleSuffix + def javaClassName = fullName('.') + moduleSuffix + /** 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. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index a53fbef200..7c382c5f93 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -95,12 +95,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } } - /** Return the suffix of a class name */ - def moduleSuffix(sym: Symbol) = - if (sym.hasModuleFlag && !sym.isMethod && - !sym.isImplClass && !sym.isJavaDefined) "$" - else "" - var pickledBytes = 0 // statistics /** @@ -161,8 +155,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val emitVars = debugLevel >= 3 override def javaName(sym: Symbol): String = { - if (sym.isClass && !sym.rawowner.isPackageClass && !sym.isModuleClass) + val isInner = sym.isClass && !sym.rawowner.isPackageClass && !sym.isModuleClass + // TODO: something atPhase(currentRun.flattenPhase.prev) which accounts for + // being nested in parameterized classes (if we're going to selectively flatten.) + if (isInner) { + log("Inner class: " + sym.fullLocationString) innerClassBuffer += sym + } super.javaName(sym) } @@ -199,7 +198,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with */ def scalaSignatureAddingMarker(jclass: JClass, sym: Symbol): Option[AnnotationInfo] = currentRun.symData get sym match { - case Some(pickle) if !jclass.getName().endsWith("$") => + case Some(pickle) if !nme.isModuleName(jclass.getName()) => val scalaAttr = fjbgContext.JOtherAttribute(jclass, jclass, tpnme.ScalaSignatureATTR.toString, versionPickle.bytes, versionPickle.writeIndex) @@ -673,7 +672,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with null else { val outerName = javaName(innerSym.rawowner) - if (isTopLevelModule(innerSym.rawowner)) outerName stripSuffix "$" + if (isTopLevelModule(innerSym.rawowner)) "" + nme.stripModuleSuffix(outerName) else outerName } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala index 9697477543..acaf1f6cc2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala @@ -87,9 +87,9 @@ trait GenJVMUtil { def javaName(sym: Symbol): String = javaNameCache.getOrElseUpdate(sym, { if (sym.isClass || (sym.isModule && !sym.isMethod)) - sym.fullName('/') + moduleSuffix(sym) + sym.javaBinaryName else - sym.simpleName.toString.trim() + moduleSuffix(sym) + sym.javaSimpleName }) def javaType(t: TypeKind): JType = (t: @unchecked) match { diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index ae2082ec8b..f2f5ecb2fe 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -1618,9 +1618,7 @@ abstract class GenMSIL extends SubComponent { * not exist in the classpath: the type checker will be very confused. */ def msilName(sym: Symbol): String = { - val suffix: String = if (sym.hasModuleFlag && !sym.isMethod && - !sym.isImplClass && - !sym.isJavaDefined) "$" else "" + val suffix = sym.moduleSuffix // Flags.JAVA: "symbol was not defined by a scala-class" (java, or .net-class) if (sym == definitions.NothingClass) @@ -2035,7 +2033,7 @@ abstract class GenMSIL extends SubComponent { } def nestingAwareFullClassname(csym: Symbol) : String = { - val suffix = moduleSuffix(csym) + val suffix = csym.moduleSuffix val res = if (csym.isNestedClass) nestingAwareFullClassname(csym.owner) + "+" + csym.encodedName else @@ -2043,12 +2041,6 @@ abstract class GenMSIL extends SubComponent { res + suffix } - /** cut&pasted from GenJVM */ - def moduleSuffix(sym: Symbol) = - if (sym.hasFlag(Flags.MODULE) && !sym.isMethod && - !sym.isImplClass && !sym.hasFlag(Flags.JAVA)) "$" - else ""; - /** Adds a static initializer which creates an instance of the module * class (calls the primary constructor). A special primary constructor * will be generated (notInitializedModules) which stores the new instance diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala index baab0271e1..4c7263ef69 100644 --- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala +++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala @@ -52,7 +52,7 @@ abstract class Changes { private val changedTypeParams = new mutable.HashSet[String] private def sameParameterSymbolNames(sym1: Symbol, sym2: Symbol): Boolean = - sameSymbol(sym1, sym2, true) || sym2.encodedName.startsWith(sym1.encodedName + "$") // see #3140 + sameSymbol(sym1, sym2, true) || sym2.encodedName.startsWith(sym1.encodedName + nme.NAME_JOIN_STRING) // see #3140 private def sameSymbol(sym1: Symbol, sym2: Symbol, simple: Boolean = false): Boolean = if (simple) sym1.encodedName == sym2.encodedName else sym1.fullName == sym2.fullName private def sameFlags(sym1: Symbol, sym2: Symbol): Boolean = diff --git a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala index 1b2f6443ae..ece80af272 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala @@ -10,6 +10,7 @@ import java.lang.reflect import java.util.concurrent.ConcurrentHashMap import util.ScalaClassLoader import ScalaClassLoader.getSystemLoader +import scala.reflect.NameTransformer._ object ByteCode { /** Until I figure out why I can't get scalap onto the classpath such @@ -17,7 +18,7 @@ object ByteCode { */ private lazy val DECODER: Option[AnyRef] = for (clazz <- getSystemLoader.tryToLoadClass[AnyRef]("scala.tools.scalap.Decode$")) yield - clazz.getField("MODULE$").get() + clazz.getField(MODULE_INSTANCE_NAME).get() private def decoderMethod(name: String, args: JClass*): Option[reflect.Method] = { for (decoder <- DECODER ; m <- Option(decoder.getClass.getMethod(name, args: _*))) yield m diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index 8e7f73296f..8ae4f9779a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -18,6 +18,7 @@ import scala.concurrent.ops import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } import interpreter._ import io.{ File, Sources } +import scala.reflect.NameTransformer._ /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. @@ -359,10 +360,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) if (rest.nonEmpty) { intp optFlatName hd match { case Some(flat) => - val clazz = flat :: rest mkString "$" + val clazz = flat :: rest mkString NAME_JOIN_STRING val bytes = super.tryClass(clazz) if (bytes.nonEmpty) bytes - else super.tryClass(clazz + "$") + else super.tryClass(clazz + MODULE_SUFFIX_STRING) case _ => super.tryClass(path) } } @@ -371,7 +372,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // we have to drop the $ to find object Foo, then tack it back onto // the end of the flattened name. def className = intp flatName path - def moduleName = (intp flatName path.stripSuffix("$")) + "$" + def moduleName = (intp flatName path.stripSuffix(MODULE_SUFFIX_STRING)) + MODULE_SUFFIX_STRING val bytes = super.tryClass(className) if (bytes.nonEmpty) bytes diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 9edf7f44f3..b84bf178a0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -209,7 +209,11 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp def quietRun[T](code: String) = beQuietDuring(interpret(code)) private def logAndDiscard[T](label: String, alt: => T): PartialFunction[Throwable, T] = { - case t => repldbg(label + ": " + t) ; alt + case t => + repldbg(label + ": " + unwrap(t)) + repltrace(util.stackTraceString(unwrap(t))) + + alt } /** whether to bind the lastException variable */ @@ -311,7 +315,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp * }}} */ def generatedName(simpleName: String): Option[String] = { - if (simpleName endsWith "$") optFlatName(simpleName.init) map (_ + "$") + if (simpleName endsWith nme.MODULE_SUFFIX_STRING) optFlatName(simpleName.init) map (_ + nme.MODULE_SUFFIX_STRING) else optFlatName(simpleName) } def flatName(id: String) = optFlatName(id) getOrElse id @@ -795,7 +799,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp * $line5.$iw$$iw$$iw$Bippy // fullFlatName */ def fullFlatName(name: String) = - lineRep.readPath + accessPath.replace('.', '$') + "$" + name + lineRep.readPath + accessPath.replace('.', '$') + nme.NAME_JOIN_STRING + name /** The unmangled symbol name, but supplemented with line info. */ def disambiguated(name: Name): String = name + " (in " + lineRep + ")" diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index 95b42ebf69..cfef2c5e87 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -188,7 +188,7 @@ abstract class Power( getCompilerClass("scala." + x).tpe case _ => val name = m.erasure.getName - if (name endsWith "$") getCompilerModule(name dropRight 1).tpe + if (name endsWith nme.MODULE_SUFFIX_STRING) getCompilerModule(name dropRight 1).tpe else { val sym = getCompilerClass(name) val args = m.typeArguments @@ -361,7 +361,7 @@ abstract class Power( object Implicits extends Implicits2 { } trait ReplUtilities { - def module[T: Manifest] = getCompilerModule(manifest[T].erasure.getName stripSuffix "$") + def module[T: Manifest] = getCompilerModule(manifest[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING) def clazz[T: Manifest] = getCompilerClass(manifest[T].erasure.getName) def info[T: Manifest] = InternalInfo[T] def ?[T: Manifest] = InternalInfo[T] diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index fc286b4868..aa926adecc 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -9,6 +9,7 @@ package interpreter import java.lang.{ reflect => r } import r.TypeVariable import scala.reflect.NameTransformer +import NameTransformer._ /** Logic for turning a type into a String. The goal is to be * able to take some arbitrary object 'x' and obtain the most precise @@ -36,17 +37,17 @@ trait TypeStrings { } toMap def scalaName(s: String): String = { - if (s endsWith "$") s.init + ".type" + if (s endsWith MODULE_SUFFIX_STRING) s.init + ".type" else if (s == "void") "scala.Unit" else if (primitives(s)) "scala." + s.capitalize - else primitiveMap.getOrElse(s, NameTransformer decode s) + else primitiveMap.getOrElse(s, NameTransformer.decode(s)) } // Trying to put humpty dumpty back together again. def scalaName(clazz: JClass): String = { val name = clazz.getName val isAnon = clazz.isScalaAnonymous val enclClass = clazz.getEnclosingClass - def enclPre = enclClass.getName + "$" + def enclPre = enclClass.getName + MODULE_SUFFIX_STRING def enclMatch = name startsWith enclPre scalaName( diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 9d3421ae27..1970a580a6 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -187,8 +187,8 @@ abstract class ClassfileParser { val start = starts(index) if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) val name = getExternalName(in.getChar(start + 1)) - if (name endsWith '$') - c = definitions.getModule(name stripEnd "$") + if (nme.isModuleName(name)) + c = definitions.getModule(nme.stripModuleSuffix(name)) else c = classNameToSymbol(name) @@ -1226,9 +1226,7 @@ abstract class ClassfileParser { innerClasses.get(externalName) match { case Some(entry) => - val outerName = - if (entry.outerName.endsWith("$")) entry.outerName.subName(0, entry.outerName.length - 1) - else entry.outerName + val outerName = nme.stripModuleSuffix(entry.outerName) val sym = classSymbol(outerName) val s = // if loading during initialization of `definitions` typerPhase is not yet set. diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 1d8588209e..b9e8abe53f 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -37,15 +37,14 @@ abstract class ICodeReader extends ClassfileParser { */ def readClass(cls: Symbol): (IClass, IClass) = { var classFile: io.AbstractFile = null; - var sym = cls - sym.info // ensure accurate type information + cls.info // ensure accurate type information isScalaModule = cls.isModule && !cls.isJavaDefined log("Reading class: " + cls + " isScalaModule?: " + isScalaModule) - val name = cls.fullName('.') + (if (sym.hasFlag(MODULE)) "$" else "") + val name = cls.javaClassName classPath.findSourceFile(name) match { - case Some(classFile) => parse(classFile, sym) + case Some(classFile) => parse(classFile, cls) case _ => throw new MissingRequirementError("Could not find bytecode for " + cls) } @@ -192,7 +191,7 @@ abstract class ICodeReader extends ClassfileParser { log("forcing " + iface.owner + " at phase: " + phase + " impl: " + iface.implClass) iface.owner.info // force the mixin type-transformer definitions.getClass(name) - } else if (name.endsWith("$")) { + } else if (name.endsWith(nme.MODULE_SUFFIX_STRING)) { val sym = forceMangledName(name.subName(0, name.length -1).decode, true) // println("classNameToSymbol: " + name + " sym: " + sym) if (name.toString == "scala.collection.immutable.Stream$$hash$colon$colon$") diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index a333c7458d..eb700f1610 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -62,7 +62,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { // The constructor parameter with given name. This means the parameter // has given name, or starts with given name, and continues with a `$` afterwards. def parameterNamed(name: Name): Symbol = { - def matchesName(param: Symbol) = param.name == name || param.name.startsWith(name + "$") + def matchesName(param: Symbol) = param.name == name || param.name.startsWith(name + nme.NAME_JOIN_STRING) (constrParams filter matchesName) match { case Nil => assert(false, name + " not in " + constrParams) ; null diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index fbb5a8dcde..c2013e77f9 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -214,10 +214,7 @@ abstract class Erasure extends AddInterfaces // Anything which could conceivably be a module (i.e. isn't known to be // a type parameter or similar) must go through here or the signature is // likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$. - def nameInSig(sym: Symbol) = "" + sym.name + global.genJVM.moduleSuffix(sym) - def fullNameInSig(sym: Symbol) = "L" + ( - atPhase(currentRun.icodePhase)(sym.fullName('/') + global.genJVM.moduleSuffix(sym)) - ) + def fullNameInSig(sym: Symbol) = "L" + atPhase(currentRun.icodePhase)(sym.javaBinaryName) def jsig(tp0: Type, existentiallyBound: List[Symbol] = Nil, toplevel: Boolean = false, primitiveOK: Boolean = true): String = { val tp = tp0.dealias @@ -266,7 +263,7 @@ abstract class Erasure extends AddInterfaces ( if (needsJavaSig(preRebound)) { val s = jsig(preRebound, existentiallyBound) - if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + nameInSig(sym) + if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName else fullNameInSig(sym) } else fullNameInSig(sym) diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index 28dfabb035..53016dd748 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -18,43 +18,69 @@ abstract class Flatten extends InfoTransform { /** the following two members override abstract members in Transform */ val phaseName: String = "flatten" + /** Updates the owning scope with the given symbol; returns the old symbol. + */ + private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = { + atPhase(phase.next) { + val scope = sym.owner.info.decls + val old = scope lookup sym.name + if (old ne NoSymbol) + scope unlink old + + scope enter sym + old + } + } + private def liftClass(sym: Symbol) { - if (!(sym hasFlag LIFTED)) { + if (!sym.isLifted) { sym setFlag LIFTED - atPhase(phase.next) { - if (settings.debug.value) log("re-enter " + sym + " in " + sym.owner) - assert(sym.owner.isPackageClass, sym) //debug - val scope = sym.owner.info.decls - val old = scope lookup sym.name - if (old != NoSymbol) scope unlink old - scope enter sym - } + debuglog("re-enter " + sym.fullLocationString) + val old = replaceSymbolInCurrentScope(sym) + if (old ne NoSymbol) + debuglog("lifted " + sym.fullLocationString + ", unlinked " + old) + } + } + private def liftSymbol(sym: Symbol) { + liftClass(sym) + if (sym.needsImplClass) + liftClass(erasure implClass sym) + } + // This is a short-term measure partially working around objects being + // lifted out of parameterized classes, leaving them referencing + // invisible type parameters. + private def isFlattenablePrefix(pre: Type) = { + val clazz = pre.typeSymbol + clazz.isClass && !clazz.isPackageClass && { + // Cannot flatten here: class A[T] { object B } + atPhase(currentRun.erasurePhase.prev)(clazz.typeParams.isEmpty) } } private val flattened = new TypeMap { def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) if (pre.typeSymbol.isClass && !pre.typeSymbol.isPackageClass) => - assert(args.isEmpty) - assert(sym.toplevelClass != NoSymbol, sym.ownerChain) - typeRef(sym.toplevelClass.owner.thisType, sym, args) + case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) => + assert(args.isEmpty && sym.toplevelClass != NoSymbol, sym.ownerChain) + typeRef(sym.toplevelClass.owner.thisType, sym, Nil) case ClassInfoType(parents, decls, clazz) => var parents1 = parents val decls1 = new Scope if (clazz.isPackageClass) { atPhase(phase.next)(decls foreach (decls1 enter _)) - } else { + } + else { val oldowner = clazz.owner atPhase(phase.next)(oldowner.info) parents1 = parents mapConserve (this) + for (sym <- decls) { if (sym.isTerm && !sym.isStaticModule) { decls1 enter sym - if (sym.isModule) sym.moduleClass setFlag LIFTED - } else if (sym.isClass) { - liftClass(sym) - if (sym.needsImplClass) liftClass(erasure.implClass(sym)) + if (sym.isModule) + sym.moduleClass setFlag LIFTED } + else if (sym.isClass) + liftSymbol(sym) } } ClassInfoType(parents1, decls1, clazz) @@ -74,7 +100,6 @@ abstract class Flatten extends InfoTransform { protected def newTransformer(unit: CompilationUnit): Transformer = new Flattener class Flattener extends Transformer { - /** Buffers for lifted out classes */ private val liftedDefs = new mutable.HashMap[Symbol, ListBuffer[Tree]] diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 7c3ace7637..533caff078 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -195,9 +195,9 @@ abstract class LambdaLift extends InfoTransform { for (sym <- renamable) { val originalName = sym.name - val base = sym.name + "$" + ( + val base = sym.name + nme.NAME_JOIN_STRING + ( if (sym.isAnonymousFunction && sym.owner.isMethod) - sym.owner.name + "$" + sym.owner.name + nme.NAME_JOIN_STRING else "" ) sym.name = diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 9e9c42cf90..6bbb94bf29 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1259,8 +1259,8 @@ trait Namers { self: Analyzer => def notMember() = context.error(tree.pos, from.decode + " is not a member of " + expr) // for Java code importing Scala objects - if (from endsWith nme.raw.DOLLAR) - isValidSelector(from stripEnd "$")(notMember()) + if (nme.isModuleName(from)) + isValidSelector(nme.stripModuleSuffix(from))(notMember()) else notMember() } diff --git a/src/compiler/scala/tools/nsc/util/Origins.scala b/src/compiler/scala/tools/nsc/util/Origins.scala index 847a9b6dad..f8ba34ae3c 100644 --- a/src/compiler/scala/tools/nsc/util/Origins.scala +++ b/src/compiler/scala/tools/nsc/util/Origins.scala @@ -6,6 +6,8 @@ package scala.tools.nsc package util +import scala.reflect.NameTransformer._ + /** A debugging class for logging from whence a method is being called. * Say you wanted to discover who was calling phase_= in SymbolTable. * You could do this: @@ -98,7 +100,7 @@ object Origins { class OneLine(clazz: Class[_]) extends Origins { type Rep = StackTraceElement - val originClass = clazz.getName stripSuffix "$" + val originClass = clazz.getName stripSuffix MODULE_SUFFIX_STRING def newRep(xs: StackSlice): Rep = xs(0) def repString(rep: Rep) = " " + rep } diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 563b2d70c4..22bb98ba46 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -10,6 +10,8 @@ package scala import scala.collection.{ mutable, immutable, generic, SetLike } import java.lang.reflect.{ Modifier, Method => JMethod, Field => JField } +import scala.reflect.NameTransformer._ +import java.util.regex.Pattern /** Defines a finite set of values specific to the enumeration. Typically * these values enumerate all possible forms something can take and provide @@ -59,11 +61,14 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable { /* Note that `readResolve` cannot be private, since otherwise the JVM does not invoke it when deserializing subclasses. */ - protected def readResolve(): AnyRef = thisenum.getClass.getField("MODULE$").get() + protected def readResolve(): AnyRef = thisenum.getClass.getField(MODULE_INSTANCE_NAME).get() /** The name of this enumeration. */ - override def toString = (getClass.getName stripSuffix "$" split '.' last) split '$' last + override def toString = ( + (getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.' last) + split Pattern.quote(NAME_JOIN_STRING) last + ) /** The mapping from the integer used to identify values to the actual * values. */ diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala index 6c12c8db33..38fbbc98f2 100755 --- a/src/library/scala/reflect/NameTransformer.scala +++ b/src/library/scala/reflect/NameTransformer.scala @@ -12,6 +12,12 @@ package scala.reflect * @author Martin Odersky */ object NameTransformer { + // XXX Short term: providing a way to alter these without having to recompile + // the compiler before recompiling the compiler. + val MODULE_SUFFIX_STRING = sys.props.getOrElse("SCALA_MODULE_SUFFIX_STRING", "$") + val NAME_JOIN_STRING = sys.props.getOrElse("SCALA_NAME_JOIN_STRING", "$") + val MODULE_INSTANCE_NAME = "MODULE$" + private val nops = 128 private val ncodes = 26 * 26 |