diff options
Diffstat (limited to 'src')
93 files changed, 697 insertions, 1322 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index c1d7176d0c..1a794f7554 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -7,17 +7,17 @@ package scala package tools package nsc -import java.io.{ File, IOException, FileNotFoundException } +import java.io.{File, FileNotFoundException, IOException} import java.net.URL -import java.nio.charset.{ Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException } -import scala.collection.{ mutable, immutable } -import io.{ SourceReader, AbstractFile, Path } +import java.nio.charset.{Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException} +import scala.collection.{immutable, mutable} +import io.{AbstractFile, Path, SourceReader} import reporters.Reporter -import util.{ ClassFileLookup, ClassPath, MergedClassPath, StatisticsInfo, returning } +import util.{ClassFileLookup, ClassPath, StatisticsInfo, returning} import scala.reflect.ClassTag -import scala.reflect.internal.util.{ ScalaClassLoader, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile } +import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, ScalaClassLoader, ScriptSourceFile, SourceFile} import scala.reflect.internal.pickling.PickleBuffer -import symtab.{ Flags, SymbolTable, SymbolTrackers } +import symtab.{Flags, SymbolTable, SymbolTrackers} import symtab.classfile.Pickler import plugins.Plugins import ast._ @@ -25,11 +25,11 @@ import ast.parser._ import typechecker._ import transform.patmat.PatternMatching import transform._ -import backend.{ ScalaPrimitives, JavaPlatform } +import backend.{JavaPlatform, ScalaPrimitives} import backend.jvm.GenBCode import scala.language.postfixOps import scala.tools.nsc.ast.{TreeGen => AstTreeGen} -import scala.tools.nsc.classpath.FlatClassPath +import scala.tools.nsc.classpath._ import scala.tools.nsc.settings.ClassPathRepresentationType class Global(var currentSettings: Settings, var reporter: Reporter) @@ -102,9 +102,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) type ThisPlatform = JavaPlatform { val global: Global.this.type } lazy val platform: ThisPlatform = new GlobalPlatform - type PlatformClassPath = ClassPath[AbstractFile] - type OptClassPath = Option[PlatformClassPath] - def classPath: ClassFileLookup[AbstractFile] = settings.YclasspathImpl.value match { case ClassPathRepresentationType.Flat => flatClassPath case ClassPathRepresentationType.Recursive => recursiveClassPath @@ -771,13 +768,17 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Extend classpath of `platform` and rescan updated packages. */ def extendCompilerClassPath(urls: URL*): Unit = { - if (settings.YclasspathImpl.value == ClassPathRepresentationType.Flat) - throw new UnsupportedOperationException("Flat classpath doesn't support extending the compiler classpath") - - val newClassPath = platform.classPath.mergeUrlsIntoClassPath(urls: _*) - platform.currentClassPath = Some(newClassPath) - // Reload all specified jars into this compiler instance - invalidateClassPathEntries(urls.map(_.getPath): _*) + if (settings.YclasspathImpl.value == ClassPathRepresentationType.Flat) { + val urlClasspaths = urls.map(u => FlatClassPathFactory.newClassPath(AbstractFile.getURL(u), settings)) + val newClassPath = AggregateFlatClassPath.createAggregate(platform.flatClassPath +: urlClasspaths : _*) + platform.currentFlatClassPath = Some(newClassPath) + invalidateClassPathEntries(urls.map(_.getPath): _*) + } else { + val newClassPath = platform.classPath.mergeUrlsIntoClassPath(urls: _*) + platform.currentClassPath = Some(newClassPath) + // Reload all specified jars into this compiler instance + invalidateClassPathEntries(urls.map(_.getPath): _*) + } } // ------------ Invalidations --------------------------------- @@ -809,43 +810,60 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * entries on the classpath. */ def invalidateClassPathEntries(paths: String*): Unit = { - if (settings.YclasspathImpl.value == ClassPathRepresentationType.Flat) - throw new UnsupportedOperationException("Flat classpath doesn't support the classpath invalidation") - - implicit object ClassPathOrdering extends Ordering[PlatformClassPath] { - def compare(a:PlatformClassPath, b:PlatformClassPath) = a.asClassPathString compare b.asClassPathString + implicit object ClassPathOrdering extends Ordering[ClassFileLookup[AbstractFile]] { + def compare(a:ClassFileLookup[AbstractFile], b:ClassFileLookup[AbstractFile]) = a.asClassPathString compare b.asClassPathString } val invalidated, failed = new mutable.ListBuffer[ClassSymbol] - classPath match { - case cp: MergedClassPath[_] => - def assoc(path: String): List[(PlatformClassPath, PlatformClassPath)] = { - val dir = AbstractFile.getDirectory(path) - val canonical = dir.canonicalPath - def matchesCanonical(e: ClassPath[_]) = e.origin match { - case Some(opath) => - AbstractFile.getDirectory(opath).canonicalPath == canonical - case None => - false - } - cp.entries find matchesCanonical match { - case Some(oldEntry) => - List(oldEntry -> cp.context.newClassPath(dir)) - case None => - error(s"Error adding entry to classpath. During invalidation, no entry named $path in classpath $classPath") - List() - } - } - val subst = immutable.TreeMap(paths flatMap assoc: _*) - if (subst.nonEmpty) { - platform updateClassPath subst - informProgress(s"classpath updated on entries [${subst.keys mkString ","}]") - def mkClassPath(elems: Iterable[PlatformClassPath]): PlatformClassPath = - if (elems.size == 1) elems.head - else new MergedClassPath(elems, recursiveClassPath.context) - val oldEntries = mkClassPath(subst.keys) - val newEntries = mkClassPath(subst.values) - mergeNewEntries(newEntries, RootClass, Some(recursiveClassPath), Some(oldEntries), invalidated, failed) - } + + def assoc(path: String): Option[(ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile])] = { + def origin(lookup: ClassFileLookup[AbstractFile]): Option[String] = lookup match { + case cp: ClassPath[_] => cp.origin + case cp: JFileDirectoryLookup[_] => Some(cp.dir.getPath) + case cp: ZipArchiveFileLookup[_] => Some(cp.zipFile.getPath) + case _ => None + } + + def entries(lookup: ClassFileLookup[AbstractFile]): Seq[ClassFileLookup[AbstractFile]] = lookup match { + case cp: ClassPath[_] => cp.entries + case cp: AggregateFlatClassPath => cp.aggregates + case cp: FlatClassPath => Seq(cp) + } + + val dir = AbstractFile.getDirectory(path) // if path is a `jar`, this is a FileZipArchive (isDirectory is true) + val canonical = dir.canonicalPath // this is the canonical path of the .jar + def matchesCanonical(e: ClassFileLookup[AbstractFile]) = origin(e) match { + case Some(opath) => + AbstractFile.getDirectory(opath).canonicalPath == canonical + case None => + false + } + entries(classPath) find matchesCanonical match { + case Some(oldEntry) => + Some(oldEntry -> ClassFileLookup.createForFile(dir, classPath, settings)) + case None => + error(s"Error adding entry to classpath. During invalidation, no entry named $path in classpath $classPath") + None + } + } + val subst = immutable.TreeMap(paths flatMap assoc: _*) + if (subst.nonEmpty) { + platform updateClassPath subst + informProgress(s"classpath updated on entries [${subst.keys mkString ","}]") + def mkClassPath(elems: Iterable[ClassFileLookup[AbstractFile]]): ClassFileLookup[AbstractFile] = + if (elems.size == 1) elems.head + else ClassFileLookup.createAggregate(elems, classPath) + val oldEntries = mkClassPath(subst.keys) + val newEntries = mkClassPath(subst.values) + classPath match { + case rcp: ClassPath[_] => mergeNewEntriesRecursive( + newEntries.asInstanceOf[ClassPath[AbstractFile]], RootClass, Some(rcp), Some(oldEntries.asInstanceOf[ClassPath[AbstractFile]]), + invalidated, failed) + + case fcp: FlatClassPath => mergeNewEntriesFlat( + RootClass, "", + oldEntries.asInstanceOf[FlatClassPath], newEntries.asInstanceOf[FlatClassPath], fcp, + invalidated, failed) + } } def show(msg: String, syms: scala.collection.Traversable[Symbol]) = if (syms.nonEmpty) @@ -876,13 +894,13 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * * Here, old means classpath, and sym means symboltable. + is presence of an entry in its column, - is absence. */ - private def mergeNewEntries(newEntries: PlatformClassPath, root: ClassSymbol, - allEntries: OptClassPath, oldEntries: OptClassPath, + private def mergeNewEntriesRecursive(newEntries: ClassPath[AbstractFile], root: ClassSymbol, + allEntries: Option[ClassPath[AbstractFile]], oldEntries: Option[ClassPath[AbstractFile]], invalidated: mutable.ListBuffer[ClassSymbol], failed: mutable.ListBuffer[ClassSymbol]) { ifDebug(informProgress(s"syncing $root, $oldEntries -> $newEntries")) - val getName: ClassPath[AbstractFile] => String = (_.name) - def hasClasses(cp: OptClassPath) = cp.isDefined && cp.get.classes.nonEmpty + val getPackageName: ClassPath[AbstractFile] => String = _.name + def hasClasses(cp: Option[ClassPath[AbstractFile]]) = cp.isDefined && cp.get.classes.nonEmpty def invalidateOrRemove(root: ClassSymbol) = { allEntries match { case Some(cp) => root setInfo new loaders.PackageLoader(cp) @@ -890,8 +908,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } invalidated += root } - def subPackage(cp: PlatformClassPath, name: String): OptClassPath = - cp.packages find (cp1 => getName(cp1) == name) + def subPackage(cp: ClassPath[AbstractFile], name: String): Option[ClassPath[AbstractFile]] = + cp.packages find (cp1 => getPackageName(cp1) == name) val classesFound = hasClasses(oldEntries) || newEntries.classes.nonEmpty if (classesFound && !isSystemPackageClass(root)) { @@ -901,22 +919,81 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (root.isRoot) invalidateOrRemove(EmptyPackageClass) else failed += root } - if (!oldEntries.isDefined) invalidateOrRemove(root) + if (oldEntries.isEmpty) invalidateOrRemove(root) else - for (pstr <- newEntries.packages.map(getName)) { + for (pstr <- newEntries.packages.map(getPackageName)) { val pname = newTermName(pstr) val pkg = (root.info decl pname) orElse { // package does not exist in symbol table, create symbol to track it - assert(!subPackage(oldEntries.get, pstr).isDefined) + assert(subPackage(oldEntries.get, pstr).isEmpty) loaders.enterPackage(root, pstr, new loaders.PackageLoader(allEntries.get)) } - mergeNewEntries(subPackage(newEntries, pstr).get, pkg.moduleClass.asClass, + mergeNewEntriesRecursive(subPackage(newEntries, pstr).get, pkg.moduleClass.asClass, subPackage(allEntries.get, pstr), subPackage(oldEntries.get, pstr), invalidated, failed) } } } + /** + * Merges new classpath entries into the symbol table + * + * @param packageClass The ClassSymbol for the package being updated + * @param fullPackageName The full name of the package being updated + * @param oldEntries The classpath that was removed, it is no longer part of fullClasspath + * @param newEntries The classpath that was added, it is already part of fullClasspath + * @param fullClasspath The full classpath, equivalent to global.classPath + * @param invalidated A ListBuffer collecting the invalidated package classes + * @param failed A ListBuffer collecting system package classes which could not be invalidated + * + * If either oldEntries or newEntries contains classes in the current package, the package symbol + * is re-initialized to a fresh package loader, provided that a corresponding package exists in + * fullClasspath. Otherwise it is removed. + * + * Otherwise, sub-packages in newEntries are looked up in the symbol table (created if + * non-existent) and the merge function is called recursively. + */ + private def mergeNewEntriesFlat( + packageClass: ClassSymbol, fullPackageName: String, + oldEntries: FlatClassPath, newEntries: FlatClassPath, fullClasspath: FlatClassPath, + invalidated: mutable.ListBuffer[ClassSymbol], failed: mutable.ListBuffer[ClassSymbol]): Unit = { + ifDebug(informProgress(s"syncing $packageClass, $oldEntries -> $newEntries")) + + def packageExists(cp: FlatClassPath): Boolean = { + val (parent, _) = PackageNameUtils.separatePkgAndClassNames(fullPackageName) + cp.packages(parent).exists(_.name == fullPackageName) + } + + def invalidateOrRemove(pkg: ClassSymbol) = { + if (packageExists(fullClasspath)) + pkg setInfo new loaders.PackageLoaderUsingFlatClassPath(fullPackageName, fullClasspath) + else + pkg.owner.info.decls unlink pkg.sourceModule + invalidated += pkg + } + + val classesFound = oldEntries.classes(fullPackageName).nonEmpty || newEntries.classes(fullPackageName).nonEmpty + if (classesFound) { + // if the package contains classes either in oldEntries or newEntries, the package is invalidated (or removed if there are no more classes in it) + if (!isSystemPackageClass(packageClass)) invalidateOrRemove(packageClass) + else if (packageClass.isRoot) invalidateOrRemove(EmptyPackageClass) + else failed += packageClass + } else { + // no new or removed classes in the current package + for (p <- newEntries.packages(fullPackageName)) { + val (_, subPackageName) = PackageNameUtils.separatePkgAndClassNames(p.name) + val subPackage = packageClass.info.decl(newTermName(subPackageName)) orElse { + // package does not exist in symbol table, create a new symbol + loaders.enterPackage(packageClass, subPackageName, new loaders.PackageLoaderUsingFlatClassPath(p.name, fullClasspath)) + } + mergeNewEntriesFlat( + subPackage.moduleClass.asClass, p.name, + oldEntries, newEntries, fullClasspath, + invalidated, failed) + } + } + } + // ----------- Runs --------------------------------------- private var curRun: Run = null diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 3167f87383..7edac76b91 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -145,6 +145,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { override def mkCast(tree: Tree, pt: Type): Tree = { debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) assert(!tree.tpe.isInstanceOf[MethodType], tree) + assert(!pt.isInstanceOf[MethodType], tree) assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) atPos(tree.pos) { mkAsInstanceOf(tree, pt, any = !phase.next.erasedTypes, wrapInApply = isAtPhaseAfter(currentRun.uncurryPhase)) diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala index 16f086e9e7..0e2f059a36 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -7,9 +7,9 @@ package scala.tools.nsc package backend import io.AbstractFile -import scala.tools.nsc.classpath.FlatClassPath +import scala.tools.nsc.classpath.{AggregateFlatClassPath, FlatClassPath} import scala.tools.nsc.settings.ClassPathRepresentationType -import scala.tools.nsc.util.{ ClassPath, DeltaClassPath, MergedClassPath } +import scala.tools.nsc.util.{ClassFileLookup, ClassPath, MergedClassPath} import scala.tools.util.FlatClassPathResolver import scala.tools.util.PathResolver @@ -29,16 +29,29 @@ trait JavaPlatform extends Platform { currentClassPath.get } - private[nsc] lazy val flatClassPath: FlatClassPath = { + private[nsc] var currentFlatClassPath: Option[FlatClassPath] = None + + private[nsc] def flatClassPath: FlatClassPath = { assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Flat, "To use flat classpath representation you must enable it with -YclasspathImpl:flat compiler option.") - new FlatClassPathResolver(settings).result + if (currentFlatClassPath.isEmpty) currentFlatClassPath = Some(new FlatClassPathResolver(settings).result) + currentFlatClassPath.get } /** Update classpath with a substituted subentry */ - def updateClassPath(subst: Map[ClassPath[AbstractFile], ClassPath[AbstractFile]]) = - currentClassPath = Some(new DeltaClassPath(currentClassPath.get, subst)) + def updateClassPath(subst: Map[ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile]]) = global.classPath match { + case cp: ClassPath[AbstractFile] => + val s = subst.asInstanceOf[Map[ClassPath[AbstractFile], ClassPath[AbstractFile]]] + currentClassPath = Some(new MergedClassPath(cp.entries map (e => s.getOrElse(e, e)), cp.context)) + + case AggregateFlatClassPath(entries) => + val s = subst.asInstanceOf[Map[FlatClassPath, FlatClassPath]] + currentFlatClassPath = Some(AggregateFlatClassPath(entries map (e => s.getOrElse(e, e)))) + + case cp: FlatClassPath => + currentFlatClassPath = Some(subst.getOrElse(cp, cp).asInstanceOf[FlatClassPath]) + } def platformPhases = List( flatten, // get rid of inner classes diff --git a/src/compiler/scala/tools/nsc/backend/Platform.scala b/src/compiler/scala/tools/nsc/backend/Platform.scala index c3bc213be1..369bcc44ed 100644 --- a/src/compiler/scala/tools/nsc/backend/Platform.scala +++ b/src/compiler/scala/tools/nsc/backend/Platform.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package backend -import util.ClassPath +import util.{ClassFileLookup, ClassPath} import io.AbstractFile import scala.tools.nsc.classpath.FlatClassPath @@ -23,7 +23,7 @@ trait Platform { private[nsc] def flatClassPath: FlatClassPath /** Update classpath with a substitution that maps entries to entries */ - def updateClassPath(subst: Map[ClassPath[AbstractFile], ClassPath[AbstractFile]]) + def updateClassPath(subst: Map[ClassFileLookup[AbstractFile], ClassFileLookup[AbstractFile]]) /** Any platform-specific phases. */ def platformPhases: List[SubComponent] diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 8a90eb9780..82aa3c65aa 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -535,6 +535,22 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { private def genApply(app: Apply, expectedType: BType): BType = { var generatedType = expectedType lineNumber(app) + + def genSuperApply(hostClass: Symbol, fun: Symbol, args: List[Tree]) = { + // 'super' call: Note: since constructors are supposed to + // return an instance of what they construct, we have to take + // special care. On JVM they are 'void', and Scala forbids (syntactically) + // to call super constructors explicitly and/or use their 'returned' value. + // therefore, we can ignore this fact, and generate code that leaves nothing + // on the stack (contrary to what the type in the AST says). + + val invokeStyle = InvokeStyle.Super + mnode.visitVarInsn(asm.Opcodes.ALOAD, 0) + genLoadArguments(args, paramTKs(app)) + genCallMethod(fun, invokeStyle, app.pos, hostClass) + generatedType = methodBTypeFromSymbol(fun).returnType + } + app match { case Apply(TypeApply(fun, targs), _) => @@ -582,19 +598,19 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { generatedType = genTypeApply() - // 'super' call: Note: since constructors are supposed to - // return an instance of what they construct, we have to take - // special care. On JVM they are 'void', and Scala forbids (syntactically) - // to call super constructors explicitly and/or use their 'returned' value. - // therefore, we can ignore this fact, and generate code that leaves nothing - // on the stack (contrary to what the type in the AST says). - case Apply(fun @ Select(Super(_, _), _), args) => - val invokeStyle = InvokeStyle.Super - // if (fun.symbol.isConstructor) Static(true) else SuperCall(mix); - mnode.visitVarInsn(asm.Opcodes.ALOAD, 0) - genLoadArguments(args, paramTKs(app)) - genCallMethod(fun.symbol, invokeStyle, app.pos) - generatedType = methodBTypeFromSymbol(fun.symbol).returnType + case Apply(fun @ Select(Super(qual, mix), _), args) => + val hostClass = qual.symbol.parentSymbols.filter(_.name == mix) match { + case Nil => + // We get here for trees created by SuperSelect which use tpnme.EMPTY as the super qualifier + // Subsequent code uses the owner of fun.symbol to target the call. + null + case parent :: Nil=> + parent + case parents => + devWarning("ambiguous parent class qualifier: " + qual.symbol.parentSymbols) + null + } + genSuperApply(hostClass, fun.symbol, args) // 'new' constructor call: Note: since constructors are // thought to return an instance of what they construct, @@ -1050,19 +1066,26 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { hostSymbol.info ; methodOwner.info def needsInterfaceCall(sym: Symbol) = ( - sym.isInterface + sym.isTraitOrInterface || sym.isJavaDefined && sym.isNonBottomSubClass(definitions.ClassfileAnnotationClass) ) + val isTraitCallToObjectMethod = + hostSymbol != methodOwner && methodOwner.isTraitOrInterface && ObjectTpe.decl(method.name) != NoSymbol && method.overrideChain.last.owner == ObjectClass + // whether to reference the type of the receiver or // the type of the method owner - val useMethodOwner = ( + val useMethodOwner = (( !style.isVirtual || hostSymbol.isBottomClass || methodOwner == definitions.ObjectClass - ) + ) && !(style.isSuper && hostSymbol != null)) || isTraitCallToObjectMethod val receiver = if (useMethodOwner) methodOwner else hostSymbol val jowner = internalName(receiver) + + if (style.isSuper && (isTraitCallToObjectMethod || receiver.isTraitOrInterface) && !cnode.interfaces.contains(jowner)) + cnode.interfaces.add(jowner) + val jname = method.javaSimpleName.toString val bmType = methodBTypeFromSymbol(method) val mdescr = bmType.descriptor @@ -1342,7 +1365,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { def asmType(sym: Symbol) = classBTypeFromSymbol(sym).toASMType val implMethodHandle = - new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else asm.Opcodes.H_INVOKEVIRTUAL, + new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else if (lambdaTarget.owner.isTrait) asm.Opcodes.H_INVOKEINTERFACE else asm.Opcodes.H_INVOKEVIRTUAL, classBTypeFromSymbol(lambdaTarget.owner).internalName, lambdaTarget.name.toString, methodBTypeFromSymbol(lambdaTarget).descriptor) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 2698225a06..324fc10eae 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -32,7 +32,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { * the InnerClass / EnclosingMethod classfile attributes. See comment in BTypes. */ def considerAsTopLevelImplementationArtifact(classSym: Symbol) = - classSym.isImplClass || classSym.isSpecialized + classSym.isSpecialized /** * Cache the value of delambdafy == "inline" for each run. We need to query this value many @@ -145,15 +145,12 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { assert(classSym.isClass, classSym) def doesNotExist(method: Symbol) = { - // (1) SI-9124, some trait methods don't exist in the generated interface. see comment in BTypes. - // (2) Value classes. Member methods of value classes exist in the generated box class. However, + // Value classes. Member methods of value classes exist in the generated box class. However, // nested methods lifted into a value class are moved to the companion object and don't exist // in the value class itself. We can identify such nested methods: the initial enclosing class // is a value class, but the current owner is some other class (the module class). - method.owner.isTrait && method.isImplOnly || { // (1) - val enclCls = nextEnclosingClass(method) - exitingPickler(enclCls.isDerivedValueClass) && method.owner != enclCls // (2) - } + val enclCls = nextEnclosingClass(method) + exitingPickler(enclCls.isDerivedValueClass) && method.owner != enclCls } def enclosingMethod(sym: Symbol): Option[Symbol] = { @@ -248,7 +245,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { * Build the [[InlineInfo]] for a class symbol. */ def buildInlineInfoFromClassSymbol(classSym: Symbol, classSymToInternalName: Symbol => InternalName, methodSymToDescriptor: Symbol => String): InlineInfo = { - val traitSelfType = if (classSym.isTrait && !classSym.isImplClass) { + val traitSelfType = if (classSym.isTrait) { // The mixin phase uses typeOfThis for the self parameter in implementation class methods. val selfSym = classSym.typeOfThis.typeSymbol if (selfSym != classSym) Some(classSymToInternalName(selfSym)) else None @@ -259,7 +256,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { val isEffectivelyFinal = classSym.isEffectivelyFinal val sam = { - if (classSym.isImplClass || classSym.isEffectivelyFinal) None + if (classSym.isEffectivelyFinal) None else { // Phase travel necessary. For example, nullary methods (getter of an abstract val) get an // empty parameter list in later phases and would therefore be picked as SAM. @@ -284,41 +281,15 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { val name = methodSym.javaSimpleName.toString // same as in genDefDef val signature = name + methodSymToDescriptor(methodSym) - // Some detours are required here because of changing flags (lateDEFERRED, lateMODULE): + // Some detours are required here because of changing flags (lateDEFERRED): // 1. Why the phase travel? Concrete trait methods obtain the lateDEFERRED flag in Mixin. // This makes isEffectivelyFinalOrNotOverridden false, which would prevent non-final // but non-overridden methods of sealed traits from being inlined. - // 2. Why the special case for `classSym.isImplClass`? Impl class symbols obtain the - // lateMODULE flag during Mixin. During the phase travel to exitingPickler, the late - // flag is ignored. The members are therefore not isEffectivelyFinal (their owner - // is not a module). Since we know that all impl class members are static, we can - // just take the shortcut. - val effectivelyFinal = classSym.isImplClass || exitingPickler(methodSym.isEffectivelyFinalOrNotOverridden) - - // Identify trait interface methods that have a static implementation in the implementation - // class. Invocations of these methods can be re-wrired directly to the static implementation - // if they are final or the receiver is known. - // - // Using `erasure.needsImplMethod` is not enough: it keeps field accessors, module getters - // and super accessors. When AddInterfaces creates the impl class, these methods are - // initially added to it. - // - // The mixin phase later on filters out most of these members from the impl class (see - // Mixin.isImplementedStatically). However, accessors for concrete lazy vals remain in the - // impl class after mixin. So the filter in mixin is not exactly what we need here (we - // want to identify concrete trait methods, not any accessors). So we check some symbol - // properties manually. - val traitMethodWithStaticImplementation = { - import symtab.Flags._ - classSym.isTrait && !classSym.isImplClass && - erasure.needsImplMethod(methodSym) && - !methodSym.isModule && - !(methodSym hasFlag (ACCESSOR | SUPERACCESSOR)) - } + val effectivelyFinal = exitingPickler(methodSym.isEffectivelyFinalOrNotOverridden) && !(methodSym.owner.isTrait && methodSym.isModule) val info = MethodInlineInfo( effectivelyFinal = effectivelyFinal, - traitMethodWithStaticImplementation = traitMethodWithStaticImplementation, + traitMethodWithStaticImplementation = false, annotatedInline = methodSym.hasAnnotation(ScalaInlineClass), annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass) ) @@ -866,7 +837,6 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { || sym.isArtifact || sym.isLiftedMethod || sym.isBridge - || (sym.ownerChain exists (_.isImplClass)) ) /* @return diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index 96796b3244..20b1a52818 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -174,7 +174,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { if (lmoc != NoSymbol) { // it must be a top level class (name contains no $s) val isCandidateForForwarders = { - exitingPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isImplClass && !lmoc.isNestedClass } + exitingPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isNestedClass } } if (isCandidateForForwarders) { log(s"Adding static forwarders from '$claszSymbol' to implementations in '$lmoc'") @@ -563,7 +563,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { } val isNative = methSymbol.hasAnnotation(definitions.NativeAttr) - val isAbstractMethod = (methSymbol.isDeferred || methSymbol.owner.isInterface) && !methSymbol.hasFlag(Flags.JAVA_DEFAULTMETHOD) + val isAbstractMethod = rhs == EmptyTree val flags = GenBCode.mkFlags( javaFlags(methSymbol), if (isAbstractMethod) asm.Opcodes.ACC_ABSTRACT else 0, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 3c2ee89b05..85563be428 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -172,7 +172,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { */ def primitiveOrClassToBType(sym: Symbol): BType = { assertClassNotArray(sym) - assert(!sym.isImplClass, sym) primitiveTypeToBType.getOrElse(sym, classBTypeFromSymbol(sym)) } @@ -337,7 +336,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { // Check for hasAnnotationFlag for SI-9393: the classfile / java source parsers add // scala.annotation.Annotation as superclass to java annotations. In reality, java // annotation classfiles have superclass Object (like any interface classfile). - val superClassSym = if (classSym.isImplClass || classSym.hasJavaAnnotationFlag) ObjectClass else { + val superClassSym = if (classSym.hasJavaAnnotationFlag) ObjectClass else { val sc = classSym.superClass // SI-9393: Java annotation classes don't have the ABSTRACT/INTERFACE flag, so they appear // (wrongly) as superclasses. Fix this for BTypes: the java annotation will appear as interface @@ -603,11 +602,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { */ final def isTopLevelModuleClass(sym: Symbol): Boolean = exitingPickler { // phase travel to pickler required for isNestedClass (looks at owner) - val r = sym.isModuleClass && !sym.isNestedClass - // The mixin phase adds the `lateMODULE` flag to trait implementation classes. Since the flag - // is late, it should not be visible here inside the time travel. We check this. - if (r) assert(!sym.isImplClass, s"isModuleClass should be false for impl class $sym") - r + sym.isModuleClass && !sym.isNestedClass } /** @@ -684,7 +679,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { val finalFlag = ( (((sym.rawflags & symtab.Flags.FINAL) != 0) || isTopLevelModuleClass(sym)) - && !sym.enclClass.isInterface + && !sym.enclClass.isTrait && !sym.isClassConstructor && !sym.isMutable // lazy vals and vars both ) @@ -697,12 +692,12 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { GenBCode.mkFlags( if (privateFlag) ACC_PRIVATE else ACC_PUBLIC, if ((sym.isDeferred && !sym.hasFlag(symtab.Flags.JAVA_DEFAULTMETHOD))|| sym.hasAbstractFlag) ACC_ABSTRACT else 0, - if (sym.isInterface) ACC_INTERFACE else 0, + if (sym.isTraitOrInterface) ACC_INTERFACE else 0, if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0, if (sym.isStaticMember) ACC_STATIC else 0, if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, if (sym.isArtifact) ACC_SYNTHETIC else 0, - if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, + if (sym.isClass && !sym.isTraitOrInterface) ACC_SUPER else 0, if (sym.hasJavaEnumFlag) ACC_ENUM else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0, if (sym.hasFlag(symtab.Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index 3617f3d863..696a164c56 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -11,7 +11,7 @@ import scala.tools.nsc.backend.jvm.BTypes.InternalName * * The symbols used to initialize the ClassBTypes may change from one compiler run to the next. To * make sure the definitions are consistent with the symbols in the current run, the - * `intializeCoreBTypes` method in BTypesFromSymbols creates a new instance of CoreBTypes in each + * `initializeCoreBTypes` method in BTypesFromSymbols creates a new instance of CoreBTypes in each * compiler run. * * The class BTypesFromSymbols does not directly reference CoreBTypes, but CoreBTypesProxy. The diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 0d6ef93a26..bd7d5d2608 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -273,7 +273,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { } // we are only interested in the class references in the descriptor, so we can skip over - // primitves and the brackets of array descriptors + // primitives and the brackets of array descriptors def visitDescriptor(desc: String): Unit = (desc.charAt(0): @switch) match { case '(' => val internalNames = mutable.ListBuffer.empty[String] @@ -455,7 +455,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { insn match { case v: VarInsnNode => val longSize = if (isSize2LoadOrStore(v.getOpcode)) 1 else 0 - maxLocals = math.max(maxLocals, v.`var` + longSize + 1) // + 1 becauase local numbers are 0-based + maxLocals = math.max(maxLocals, v.`var` + longSize + 1) // + 1 because local numbers are 0-based case i: IincInsnNode => maxLocals = math.max(maxLocals, i.`var` + 1) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala index 894799bf36..419c686bd8 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala @@ -441,10 +441,10 @@ trait ProdConsAnalyzerImpl { * return a; * } * - * In the first frame of the method, the SoruceValue for parameter `a` gives an empty set of + * In the first frame of the method, the SourceValue for parameter `a` gives an empty set of * producer instructions. * - * In the frame of the `IRETURN` instruction, the SoruceValue for parameter `a` lists a single + * In the frame of the `IRETURN` instruction, the SourceValue for parameter `a` lists a single * producer instruction: the `ISTORE 1`. This makes it look as if there was a single producer for * `a`, where in fact it might still hold the parameter's initial value. */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/package.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/package.scala index f1ac703532..ef961941a0 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/package.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/package.scala @@ -43,7 +43,7 @@ package scala.tools.nsc.backend.jvm * - Stores a frame for each instruction * - `merge` function takes an instruction and a frame, merges the existing frame for that instr * (from the frames array) with the new frame passed as argument. - * if the frame changed, puts the instruction on the work queue (fixpiont). + * if the frame changed, puts the instruction on the work queue (fixpoint). * - initial frame: initialized for first instr by calling interpreter.new[...]Value * for each slot (locals and params), stored in frames[firstInstr] by calling `merge` * - work queue of instructions (`queue` array, `top` index for next instruction to analyze) @@ -191,7 +191,7 @@ package scala.tools.nsc.backend.jvm * I measured nullness analysis (which tracks aliases) and a SimpleValue analysis. Nullness runs * roughly 5x slower (because of alias tracking) at every problem size - this factor doesn't change. * - * The numbers below are for nullness. Note that the the last column is constant, i.e., the running + * The numbers below are for nullness. Note that the last column is constant, i.e., the running * time is proportional to #ins * #loc^2. Therefore we use this factor when limiting the maximal * method size for running an analysis. * diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index 17255cb880..6dd74bad84 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -137,7 +137,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { callee = method, calleeDeclarationClass = declarationClassBType, safeToInline = safeToInline, - safeToRewrite = safeToRewrite, + safeToRewrite = false, canInlineFromSource = canInlineFromSource, annotatedInline = annotatedInline, annotatedNoInline = annotatedNoInline, @@ -299,7 +299,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { receiverType.info.orThrow.inlineInfo.isEffectivelyFinal // (1) } - val isRewritableTraitCall = isStaticallyResolved && methodInlineInfo.traitMethodWithStaticImplementation + val isRewritableTraitCall = false val warning = calleeDeclarationClassBType.info.orThrow.inlineInfo.warning.map( MethodInlineInfoIncomplete(calleeDeclarationClassBType.internalName, calleeMethodNode.name, calleeMethodNode.desc, _)) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala index 58054f85ad..4935b9d1a0 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala @@ -156,7 +156,7 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) { // TODO: This is maybe over-cautious. // We are checking if the closure body method is accessible at the closure callsite. // If the closure allocation has access to the body method, then the callsite (in the same - // method as the alloction) should have access too. + // method as the allocation) should have access too. val bodyAccessible: Either[OptimizerWarning, Boolean] = for { (bodyMethodNode, declClass) <- byteCodeRepository.methodNode(lambdaBodyHandle.getOwner, lambdaBodyHandle.getName, lambdaBodyHandle.getDesc): Either[OptimizerWarning, (MethodNode, InternalName)] isAccessible <- inliner.memberIsAccessible(bodyMethodNode.access, classBTypeFromParsedClassfile(declClass), classBTypeFromParsedClassfile(lambdaBodyHandle.getOwner), ownerClass) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala index f91530903d..f1eaebd27c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala @@ -52,7 +52,7 @@ class CopyProp[BT <: BTypes](val btypes: BT) { var r = init while (it.hasNext) { val n = it.next() - // knownUsed.lenght is the number of locals, `n` may be a stack slot + // knownUsed.length is the number of locals, `n` may be a stack slot if (n < knownUsed.length && knownUsed(n)) return n if (n < r) r = n } @@ -171,7 +171,7 @@ class CopyProp[BT <: BTypes](val btypes: BT) { * * A special case eliminates the creation of unused objects with side-effect-free constructors: * NEW scala/Tuple1; DUP; ALOAD 0; INVOKESPECIAL scala/Tuple1.<init>; POP - * The POP has a signle producer (the DUP), it's easy to eliminate these two. A special case + * The POP has a single producer (the DUP), it's easy to eliminate these two. A special case * is needed to eliminate the INVOKESPECIAL and NEW. */ def eliminatePushPop(method: MethodNode, owner: InternalName): Boolean = { @@ -533,7 +533,7 @@ class CopyProp[BT <: BTypes](val btypes: BT) { } /** - * Try to pair `insn` with its correspondant on the stack + * Try to pair `insn` with its correspondent on the stack * - if the stack top is a store and `insn` is a corresponding load, create a pair * - otherwise, check the two top stack values for `null; store`. if it matches, create * a pair and continue pairing `insn` on the remaining stack diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index 9847c9db58..32106614e3 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -27,7 +27,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { import backendUtils._ def runInliner(): Unit = { - rewriteFinalTraitMethodInvocations() +// rewriteFinalTraitMethodInvocations() for (request <- collectAndOrderInlineRequests) { val Right(callee) = request.callsite.callee // collectAndOrderInlineRequests returns callsites with a known callee diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala index f486bb0cb9..085463633f 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -504,7 +504,7 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { case v: VarInsnNode if isLive => val longSize = if (isSize2LoadOrStore(v.getOpcode)) 1 else 0 - maxLocals = math.max(maxLocals, v.`var` + longSize + 1) // + 1 becauase local numbers are 0-based + maxLocals = math.max(maxLocals, v.`var` + longSize + 1) // + 1 because local numbers are 0-based case i: IincInsnNode if isLive => maxLocals = math.max(maxLocals, i.`var` + 1) diff --git a/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala index 3f06264e3c..f97d97548e 100644 --- a/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/AggregateFlatClassPath.scala @@ -18,7 +18,6 @@ import scala.tools.nsc.util.ClassRepresentation * @param aggregates classpath instances containing entries which this class processes */ case class AggregateFlatClassPath(aggregates: Seq[FlatClassPath]) extends FlatClassPath { - override def findClassFile(className: String): Option[AbstractFile] = { @tailrec def find(aggregates: Seq[FlatClassPath]): Option[AbstractFile] = @@ -37,8 +36,7 @@ case class AggregateFlatClassPath(aggregates: Seq[FlatClassPath]) extends FlatCl @tailrec def findEntry[T <: ClassRepClassPathEntry](aggregates: Seq[FlatClassPath], getEntries: FlatClassPath => Seq[T]): Option[T] = if (aggregates.nonEmpty) { - val entry = getEntries(aggregates.head) - .find(_.name == simpleClassName) + val entry = getEntries(aggregates.head).find(_.name == simpleClassName) if (entry.isDefined) entry else findEntry(aggregates.tail, getEntries) } else None @@ -46,7 +44,11 @@ case class AggregateFlatClassPath(aggregates: Seq[FlatClassPath]) extends FlatCl val classEntry = findEntry(aggregates, classesGetter(pkg)) val sourceEntry = findEntry(aggregates, sourcesGetter(pkg)) - mergeClassesAndSources(classEntry.toList, sourceEntry.toList).headOption + (classEntry, sourceEntry) match { + case (Some(c), Some(s)) => Some(ClassAndSourceFilesEntry(c.file, s.file)) + case (c @ Some(_), _) => c + case (_, s) => s + } } override def asURLs: Seq[URL] = aggregates.flatMap(_.asURLs) @@ -123,3 +125,15 @@ case class AggregateFlatClassPath(aggregates: Seq[FlatClassPath]) extends FlatCl private def classesGetter(pkg: String) = (cp: FlatClassPath) => cp.classes(pkg) private def sourcesGetter(pkg: String) = (cp: FlatClassPath) => cp.sources(pkg) } + +object AggregateFlatClassPath { + def createAggregate(parts: FlatClassPath*): FlatClassPath = { + val elems = new ArrayBuffer[FlatClassPath]() + parts foreach { + case AggregateFlatClassPath(ps) => elems ++= ps + case p => elems += p + } + if (elems.size == 1) elems.head + else AggregateFlatClassPath(elems.toIndexedSeq) + } +} diff --git a/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala index 81d2f7320f..e3964dfa78 100644 --- a/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/DirectoryFlatClassPath.scala @@ -4,7 +4,6 @@ package scala.tools.nsc.classpath import java.io.File -import java.io.FileFilter import java.net.URL import scala.reflect.io.AbstractFile import scala.reflect.io.PlainFile @@ -12,97 +11,101 @@ import scala.tools.nsc.util.ClassRepresentation import FileUtils._ /** - * A trait allowing to look for classpath entries of given type in directories. - * It provides common logic for classes handling class and source files. + * A trait allowing to look for classpath entries in directories. It provides common logic for + * classes handling class and source files. * It makes use of the fact that in the case of nested directories it's easy to find a file * when we have a name of a package. + * It abstracts over the file representation to work with both JFile and AbstractFile. */ -trait DirectoryFileLookup[FileEntryType <: ClassRepClassPathEntry] extends FlatClassPath { - val dir: File - assert(dir != null, "Directory file in DirectoryFileLookup cannot be null") +trait DirectoryLookup[FileEntryType <: ClassRepClassPathEntry] extends FlatClassPath { + type F + + val dir: F + + protected def emptyFiles: Array[F] // avoids reifying ClassTag[F] + protected def getSubDir(dirName: String): Option[F] + protected def listChildren(dir: F, filter: Option[F => Boolean] = None): Array[F] + protected def getName(f: F): String + protected def toAbstractFile(f: F): AbstractFile + protected def isPackage(f: F): Boolean - override def asURLs: Seq[URL] = Seq(dir.toURI.toURL) - override def asClassPathStrings: Seq[String] = Seq(dir.getPath) + protected def createFileEntry(file: AbstractFile): FileEntryType + protected def isMatchingFile(f: F): Boolean - import FlatClassPath.RootPackage - private def getDirectory(forPackage: String): Option[File] = { - if (forPackage == RootPackage) { + private def getDirectory(forPackage: String): Option[F] = { + if (forPackage == FlatClassPath.RootPackage) { Some(dir) } else { val packageDirName = FileUtils.dirPath(forPackage) - val packageDir = new File(dir, packageDirName) - if (packageDir.exists && packageDir.isDirectory) { - Some(packageDir) - } else None + getSubDir(packageDirName) } } - override private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { + private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { val dirForPackage = getDirectory(inPackage) - val nestedDirs: Array[File] = dirForPackage match { - case None => Array.empty - case Some(directory) => directory.listFiles(DirectoryFileLookup.packageDirectoryFileFilter) + val nestedDirs: Array[F] = dirForPackage match { + case None => emptyFiles + case Some(directory) => listChildren(directory, Some(isPackage)) } val prefix = PackageNameUtils.packagePrefix(inPackage) - val entries = nestedDirs map { file => - PackageEntryImpl(prefix + file.getName) - } - entries + nestedDirs.map(f => PackageEntryImpl(prefix + getName(f))) } protected def files(inPackage: String): Seq[FileEntryType] = { val dirForPackage = getDirectory(inPackage) - val files: Array[File] = dirForPackage match { - case None => Array.empty - case Some(directory) => directory.listFiles(fileFilter) - } - val entries = files map { file => - val wrappedFile = new scala.reflect.io.File(file) - createFileEntry(new PlainFile(wrappedFile)) + val files: Array[F] = dirForPackage match { + case None => emptyFiles + case Some(directory) => listChildren(directory, Some(isMatchingFile)) } - entries + files.map(f => createFileEntry(toAbstractFile(f))) } - override private[nsc] def list(inPackage: String): FlatClassPathEntries = { + private[nsc] def list(inPackage: String): FlatClassPathEntries = { val dirForPackage = getDirectory(inPackage) - val files: Array[File] = dirForPackage match { - case None => Array.empty - case Some(directory) => directory.listFiles() + val files: Array[F] = dirForPackage match { + case None => emptyFiles + case Some(directory) => listChildren(directory) } val packagePrefix = PackageNameUtils.packagePrefix(inPackage) val packageBuf = collection.mutable.ArrayBuffer.empty[PackageEntry] val fileBuf = collection.mutable.ArrayBuffer.empty[FileEntryType] for (file <- files) { - if (file.isPackage) { - val pkgEntry = PackageEntryImpl(packagePrefix + file.getName) - packageBuf += pkgEntry - } else if (fileFilter.accept(file)) { - val wrappedFile = new scala.reflect.io.File(file) - val abstractFile = new PlainFile(wrappedFile) - fileBuf += createFileEntry(abstractFile) - } + if (isPackage(file)) + packageBuf += PackageEntryImpl(packagePrefix + getName(file)) + else if (isMatchingFile(file)) + fileBuf += createFileEntry(toAbstractFile(file)) } FlatClassPathEntries(packageBuf, fileBuf) } - - protected def createFileEntry(file: AbstractFile): FileEntryType - protected def fileFilter: FileFilter } -object DirectoryFileLookup { +trait JFileDirectoryLookup[FileEntryType <: ClassRepClassPathEntry] extends DirectoryLookup[FileEntryType] { + type F = File - private[classpath] object packageDirectoryFileFilter extends FileFilter { - override def accept(pathname: File): Boolean = pathname.isPackage + protected def emptyFiles: Array[File] = Array.empty + protected def getSubDir(packageDirName: String): Option[File] = { + val packageDir = new File(dir, packageDirName) + if (packageDir.exists && packageDir.isDirectory) Some(packageDir) + else None } -} + protected def listChildren(dir: File, filter: Option[File => Boolean]): Array[File] = filter match { + case Some(f) => dir.listFiles(mkFileFilter(f)) + case None => dir.listFiles() + } + protected def getName(f: File): String = f.getName + protected def toAbstractFile(f: File): AbstractFile = new PlainFile(new scala.reflect.io.File(f)) + protected def isPackage(f: File): Boolean = f.isPackage -case class DirectoryFlatClassPath(dir: File) - extends DirectoryFileLookup[ClassFileEntryImpl] - with NoSourcePaths { + assert(dir != null, "Directory file in DirectoryFileLookup cannot be null") + def asURLs: Seq[URL] = Seq(dir.toURI.toURL) + def asClassPathStrings: Seq[String] = Seq(dir.getPath) +} + +case class DirectoryFlatClassPath(dir: File) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = findClassFile(className) map ClassFileEntryImpl - override def findClassFile(className: String): Option[AbstractFile] = { + def findClassFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) val classFile = new File(s"$dir/$relativePath.class") if (classFile.exists) { @@ -112,31 +115,19 @@ case class DirectoryFlatClassPath(dir: File) } else None } - override protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) - override protected def fileFilter: FileFilter = DirectoryFlatClassPath.classFileFilter - - override private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) -} - -object DirectoryFlatClassPath { + protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) + protected def isMatchingFile(f: File): Boolean = f.isClass - private val classFileFilter = new FileFilter { - override def accept(pathname: File): Boolean = pathname.isClass - } + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) } -case class DirectoryFlatSourcePath(dir: File) - extends DirectoryFileLookup[SourceFileEntryImpl] - with NoClassPaths { +case class DirectoryFlatSourcePath(dir: File) extends JFileDirectoryLookup[SourceFileEntryImpl] with NoClassPaths { + def asSourcePathString: String = asClassPathString - override def asSourcePathString: String = asClassPathString + protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file) + protected def isMatchingFile(f: File): Boolean = endsScalaOrJava(f.getName) - override protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file) - override protected def fileFilter: FileFilter = DirectoryFlatSourcePath.sourceFileFilter - - override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = { - findSourceFile(className) map SourceFileEntryImpl - } + override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = findSourceFile(className) map SourceFileEntryImpl private def findSourceFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) @@ -151,12 +142,5 @@ case class DirectoryFlatSourcePath(dir: File) } } - override private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = files(inPackage) -} - -object DirectoryFlatSourcePath { - - private val sourceFileFilter = new FileFilter { - override def accept(pathname: File): Boolean = endsScalaOrJava(pathname.getName) - } + private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = files(inPackage) } diff --git a/src/compiler/scala/tools/nsc/classpath/FileUtils.scala b/src/compiler/scala/tools/nsc/classpath/FileUtils.scala index ee2528e15c..bbcfcb24ca 100644 --- a/src/compiler/scala/tools/nsc/classpath/FileUtils.scala +++ b/src/compiler/scala/tools/nsc/classpath/FileUtils.scala @@ -3,7 +3,7 @@ */ package scala.tools.nsc.classpath -import java.io.{ File => JFile } +import java.io.{File => JFile, FileFilter} import java.net.URL import scala.reflect.internal.FatalError import scala.reflect.io.AbstractFile @@ -65,4 +65,8 @@ object FileUtils { // because then some tests in partest don't pass private def mayBeValidPackage(dirName: String): Boolean = (dirName != "META-INF") && (dirName != "") && (dirName.charAt(0) != '.') + + def mkFileFilter(f: JFile => Boolean) = new FileFilter { + def accept(pathname: JFile): Boolean = f(pathname) + } } diff --git a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala index cb201617d2..e95ffe02e3 100644 --- a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala @@ -28,11 +28,8 @@ trait FlatClassPath extends ClassFileLookup[AbstractFile] { override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = { val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) - val foundClassFromClassFiles = classes(pkg) - .find(_.name == simpleClassName) - - def findClassInSources = sources(pkg) - .find(_.name == simpleClassName) + val foundClassFromClassFiles = classes(pkg).find(_.name == simpleClassName) + def findClassInSources = sources(pkg).find(_.name == simpleClassName) foundClassFromClassFiles orElse findClassInSources } @@ -50,7 +47,7 @@ case class FlatClassPathEntries(packages: Seq[PackageEntry], classesAndSources: object FlatClassPathEntries { import scala.language.implicitConversions // to have working unzip method - implicit def entry2Tuple(entry: FlatClassPathEntries) = (entry.packages, entry.classesAndSources) + implicit def entry2Tuple(entry: FlatClassPathEntries): (Seq[PackageEntry], Seq[ClassRepClassPathEntry]) = (entry.packages, entry.classesAndSources) } sealed trait ClassRepClassPathEntry extends ClassRepresentation[AbstractFile] diff --git a/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala b/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala index d8ca325885..463301696e 100644 --- a/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala +++ b/src/compiler/scala/tools/nsc/classpath/FlatClassPathFactory.scala @@ -3,6 +3,7 @@ */ package scala.tools.nsc.classpath +import scala.reflect.io.VirtualDirectory import scala.tools.nsc.Settings import scala.tools.nsc.io.AbstractFile import FileUtils.AbstractFileOps @@ -12,16 +13,9 @@ import FileUtils.AbstractFileOps * it uses proper type of classpath depending on a types of particular files containing sources or classes. */ class FlatClassPathFactory(settings: Settings) extends ClassPathFactory[FlatClassPath] { + def newClassPath(file: AbstractFile): FlatClassPath = FlatClassPathFactory.newClassPath(file, settings) - override def newClassPath(file: AbstractFile): FlatClassPath = - if (file.isJarOrZip) - ZipAndJarFlatClassPathFactory.create(file, settings) - else if (file.isDirectory) - new DirectoryFlatClassPath(file.file) - else - sys.error(s"Unsupported classpath element: $file") - - override def sourcesInPath(path: String): List[FlatClassPath] = + def sourcesInPath(path: String): List[FlatClassPath] = for { file <- expandPath(path, expandStar = false) dir <- Option(AbstractFile getDirectory file) @@ -35,3 +29,16 @@ class FlatClassPathFactory(settings: Settings) extends ClassPathFactory[FlatClas else sys.error(s"Unsupported sourcepath element: $file") } + +object FlatClassPathFactory { + def newClassPath(file: AbstractFile, settings: Settings): FlatClassPath = file match { + case vd: VirtualDirectory => VirtualDirectoryFlatClassPath(vd) + case _ => + if (file.isJarOrZip) + ZipAndJarFlatClassPathFactory.create(file, settings) + else if (file.isDirectory) + new DirectoryFlatClassPath(file.file) + else + sys.error(s"Unsupported classpath element: $file") + } +} diff --git a/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala new file mode 100644 index 0000000000..06cdab583c --- /dev/null +++ b/src/compiler/scala/tools/nsc/classpath/VirtualDirectoryFlatClassPath.scala @@ -0,0 +1,39 @@ +package scala.tools.nsc.classpath + +import scala.tools.nsc.util.ClassRepresentation +import scala.reflect.io.{Path, PlainFile, VirtualDirectory, AbstractFile} +import FileUtils._ +import java.net.URL + +case class VirtualDirectoryFlatClassPath(dir: VirtualDirectory) extends FlatClassPath with DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { + type F = AbstractFile + + protected def emptyFiles: Array[AbstractFile] = Array.empty + protected def getSubDir(packageDirName: String): Option[AbstractFile] = + Option(dir.lookupName(packageDirName, directory = true)) + protected def listChildren(dir: AbstractFile, filter: Option[AbstractFile => Boolean] = None): Array[F] = filter match { + case Some(f) => dir.iterator.filter(f).toArray + case _ => dir.toArray + } + def getName(f: AbstractFile): String = f.name + def toAbstractFile(f: AbstractFile): AbstractFile = f + def isPackage(f: AbstractFile): Boolean = f.isPackage + + // mimic the behavior of the old nsc.util.DirectoryClassPath + def asURLs: Seq[URL] = Seq(new URL(dir.name)) + def asClassPathStrings: Seq[String] = Seq(dir.path) + + override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = findClassFile(className) map ClassFileEntryImpl + + def findClassFile(className: String): Option[AbstractFile] = { + val relativePath = FileUtils.dirPath(className) + val classFile = new PlainFile(Path(s"$dir/$relativePath.class")) + if (classFile.exists) Some(classFile) + else None + } + + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) + + protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) + protected def isMatchingFile(f: AbstractFile): Boolean = f.isClass +} diff --git a/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala b/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala index 85c7c3c843..6ec3805d8b 100644 --- a/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala +++ b/src/compiler/scala/tools/nsc/classpath/ZipAndJarFileLookupFactory.scala @@ -19,7 +19,6 @@ import FileUtils._ * when there are a lot of projects having a lot of common dependencies. */ sealed trait ZipAndJarFileLookupFactory { - private val cache = collection.mutable.Map.empty[AbstractFile, FlatClassPath] def create(zipFile: AbstractFile, settings: Settings): FlatClassPath = { @@ -44,7 +43,6 @@ sealed trait ZipAndJarFileLookupFactory { * It should be the only way of creating them as it provides caching. */ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { - private case class ZipArchiveFlatClassPath(zipFile: File) extends ZipArchiveFileLookup[ClassFileEntryImpl] with NoSourcePaths { @@ -67,10 +65,7 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { * with a particularly prepared scala-library.jar. It should have all classes listed in the manifest like e.g. this entry: * Name: scala/Function2$mcFJD$sp.class */ - private case class ManifestResourcesFlatClassPath(file: ManifestResources) - extends FlatClassPath - with NoSourcePaths { - + private case class ManifestResourcesFlatClassPath(file: ManifestResources) extends FlatClassPath with NoSourcePaths { override def findClassFile(className: String): Option[AbstractFile] = { val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) classes(pkg).find(_.name == simpleClassName).map(_.file) @@ -163,7 +158,6 @@ object ZipAndJarFlatClassPathFactory extends ZipAndJarFileLookupFactory { * It should be the only way of creating them as it provides caching. */ object ZipAndJarFlatSourcePathFactory extends ZipAndJarFileLookupFactory { - private case class ZipArchiveFlatSourcePath(zipFile: File) extends ZipArchiveFileLookup[SourceFileEntryImpl] with NoClassPaths { diff --git a/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala b/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala index 1d0de57779..a24d989306 100644 --- a/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala +++ b/src/compiler/scala/tools/nsc/classpath/ZipArchiveFileLookup.scala @@ -57,7 +57,7 @@ trait ZipArchiveFileLookup[FileEntryType <: ClassRepClassPathEntry] extends Flat } getOrElse FlatClassPathEntries(Seq.empty, Seq.empty) } - private def findDirEntry(pkg: String) = { + private def findDirEntry(pkg: String): Option[archive.DirEntry] = { val dirName = s"${FileUtils.dirPath(pkg)}/" archive.allDirs.get(dirName) } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 7224523a41..8cdc5944e8 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -509,7 +509,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { EmptyTree } } - // for abstract methods (of classes), the `DEFERRED` flag is alredy set. + // for abstract methods (of classes), the `DEFERRED` flag is already set. // here we also set it for interface methods that are not static and not default. if (!isConcreteInterfaceMethod) mods1 |= Flags.DEFERRED List { diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index c524121646..982a6da41a 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -199,7 +199,7 @@ trait ScalaSettings extends AbsScalaSettings val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overridden methods.") val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212) val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212) - val YclasspathImpl = ChoiceSetting ("-YclasspathImpl", "implementation", "Choose classpath scanning method.", List(ClassPathRepresentationType.Recursive, ClassPathRepresentationType.Flat), ClassPathRepresentationType.Recursive) + val YclasspathImpl = ChoiceSetting ("-YclasspathImpl", "implementation", "Choose classpath scanning method.", List(ClassPathRepresentationType.Recursive, ClassPathRepresentationType.Flat), ClassPathRepresentationType.Flat) val YdisableFlatCpCaching = BooleanSetting ("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.") val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 085a814c6b..1cee76ae65 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -14,202 +14,12 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => import global._ // the global environment import definitions._ // standard classes and methods - /** The phase sets lateINTERFACE for non-interface traits that now - * become interfaces. It sets lateDEFERRED for formerly concrete - * methods in such traits. + /** lateDEFERRED for formerly concrete methods in such traits. */ - override def phaseNewFlags: Long = lateDEFERRED | lateINTERFACE - - /** A lazily constructed map that associates every non-interface trait with - * its implementation class. - */ - private val implClassMap = perRunCaches.newMap[Symbol, Symbol]() - - /** A lazily constructed map that associates every concrete method in a non-interface - * trait that's currently compiled with its corresponding method in the trait's - * implementation class. - */ - private val implMethodMap = perRunCaches.newMap[Symbol, Symbol]() - - override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = { - implClassMap.clear() - implMethodMap.clear() - super.newPhase(prev) - } - - /** Is given trait member symbol a member of the trait's interface - * after this transform is performed? - */ - private def isInterfaceMember(sym: Symbol) = ( - sym.isType || { - sym.info // initialize to set lateMETHOD flag if necessary - - ( sym.isMethod - && !sym.isLabel - && !sym.isPrivate - && (!(sym hasFlag BRIDGE) || sym.hasBridgeAnnotation) // count @bridge annotated classes as interface members - && !sym.isConstructor - && !sym.isImplOnly - ) - } - ) - - /** Does symbol need an implementation method? */ - def needsImplMethod(sym: Symbol) = ( - sym.isMethod - && isInterfaceMember(sym) - && (!sym.hasFlag(DEFERRED | SUPERACCESSOR) || (sym hasFlag lateDEFERRED)) - ) - - def implClassPhase = currentRun.erasurePhase.next - - private def newImplClass(iface: Symbol): Symbol = { - val inClass = iface.owner.isClass - val implName = tpnme.implClassName(iface.name) - val implFlags = (iface.flags & ~(INTERFACE | lateINTERFACE)) | IMPLCLASS - - val impl0 = { - if (!inClass) NoSymbol - else { - val typeInfo = iface.owner.info - typeInfo.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. - // TODO this is not taken into account by flat classpath yet - classPath match { - case cp: ClassPath[_] if !cp.context.isValidName(implName + ".class") => - log(s"not unlinking $iface's existing implClass ${implSym.name} because it is not on the classpath.") - implSym - case _ => - typeInfo.decls unlink implSym - NoSymbol - } - } - } - } - - 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.associatedFile = 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 if one does not yet exist */ - def implClass(iface: Symbol): Symbol = { - iface.info - - implClassMap.getOrElse(iface, enteringPhase(implClassPhase) { - if (iface.implClass eq NoSymbol) - debuglog(s"${iface.fullLocationString} has no implClass yet, creating it now.") - else - log(s"${iface.fullLocationString} impl class is ${iface.implClass.nameString}") - - newImplClass(iface) - }) - } - - /** A lazy type to set the info of an implementation class - * The parents of an implementation class for trait iface are: - * - * - superclass: Object - * - mixin classes: mixin classes of iface where every non-interface - * trait is mapped to its implementation class, followed by iface itself. - * - * The declarations of a mixin class are: - * - for every interface member of iface: its implementation method, if one is needed - * - every former member of iface that is implementation only - */ - private class LazyImplClassType(iface: Symbol) extends LazyType with FlagAgnosticCompleter { - /** Compute the decls of implementation class implClass, - * given the decls ifaceDecls of its interface. - */ - private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = { - debuglog("LazyImplClassType calculating decls for " + implClass) - - val decls = newScope - 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, UnitTpe) - ) - } - - for (sym <- ifaceDecls) { - if (isInterfaceMember(sym)) { - if (needsImplMethod(sym)) { - val clone = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED) - if (currentRun.compiles(implClass)) implMethodMap(sym) = clone - decls enter clone - sym setFlag lateDEFERRED - if (!sym.isSpecialized) - log(s"Cloned ${sym.name} from ${sym.owner} into implClass ${implClass.fullName}") - } - } - else { - log(s"Destructively modifying owner of $sym from ${sym.owner} to $implClass") - sym.owner = implClass - // note: OK to destructively modify the owner here, - // because symbol will not be accessible from outside the sourcefile. - // mixin constructors are corrected separately; see TermSymbol.owner - decls enter sym - } - } - - decls - } - - override def complete(implSym: Symbol) { - debuglog("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 = AddInterfaces.this.erasure(implSym) { - tp match { //@MATN: no normalize needed (comes after erasure) - case TypeRef(pre, sym, _) if sym.needsImplClass => - typeRef(pre, implClass(sym), Nil) - case _ => - tp - } - } - def implType(tp: Type): Type = tp match { - case ClassInfoType(parents, decls, _) => - assert(phase == implClassPhase, tp) - // Impl class parents: Object first, matching interface last. - val implParents = ObjectTpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe - ClassInfoType(implParents, implDecls(implSym, decls), implSym) - case PolyType(_, restpe) => - implType(restpe) - } - implSym setInfo implType(enteringErasure(iface.info)) - } - - override def load(clazz: Symbol) { complete(clazz) } - } + override def phaseNewFlags: Long = lateDEFERRED def transformMixinInfo(tp: Type): Type = tp match { case ClassInfoType(parents, decls, clazz) if clazz.isPackageClass || !clazz.isJavaDefined => - if (clazz.needsImplClass) - implClass(clazz setFlag lateINTERFACE) // generate an impl class val parents1 = parents match { case Nil => Nil @@ -218,21 +28,20 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => if (clazz.isTrait) ObjectTpe :: tl else parents } - val decls1 = scopeTransform(clazz)( - decls filter (sym => - if (clazz.isInterface) isInterfaceMember(sym) - else sym.isClass || sym.isTerm - ) - ) - ClassInfoType(parents1, decls1, clazz) + if (clazz.isTrait) { + decls foreach { sym => + if (!sym.isType) sym.info // initialize to set lateMETHOD flag if necessary + } + } + if (parents1 eq parents) tp + else ClassInfoType(parents1, decls, clazz) case _ => tp } // Tree transformation -------------------------------------------------------------- - private class ChangeOwnerAndReturnTraverser(oldowner: Symbol, newowner: Symbol) - extends ChangeOwnerTraverser(oldowner, newowner) { + extends ChangeOwnerTraverser(oldowner, newowner) { override def traverse(tree: Tree) { tree match { case _: Return => change(tree.symbol) @@ -242,61 +51,10 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } } - private def isInterfaceTree(tree: Tree) = tree.isDef && isInterfaceMember(tree.symbol) - - private def deriveMemberForImplClass(tree: Tree): Tree = - if (isInterfaceTree(tree)) if (needsImplMethod(tree.symbol)) implMethodDef(tree) else EmptyTree - else tree - - private def deriveMemberForInterface(tree: Tree): Tree = - if (isInterfaceTree(tree)) if (needsImplMethod(tree.symbol)) DefDef(tree.symbol, EmptyTree) else tree - else EmptyTree - - private def ifaceTemplate(templ: Template): Template = - treeCopy.Template(templ, templ.parents, noSelfType, templ.body map deriveMemberForInterface) - - /** Transforms the member tree containing the implementation - * into a member of the impl class. - */ - private def implMethodDef(tree: Tree): Tree = { - val impl = implMethodMap.getOrElse(tree.symbol, abort("implMethod missing for " + tree.symbol)) - - val newTree = if (impl.isErroneous) tree else { // e.g. res/t687 - // SI-5167: Ensure that the tree that we are grafting refers the parameter symbols from the - // new method symbol `impl`, rather than the symbols of the original method signature in - // the trait. `tree setSymbol impl` does *not* suffice! - val DefDef(_, _, _, vparamss, _, _) = tree - val oldSyms = vparamss.flatten.map(_.symbol) - val newSyms = impl.info.paramss.flatten - assert(oldSyms.length == newSyms.length, (oldSyms, impl, impl.info)) - tree.substituteSymbols(oldSyms, newSyms) - } - new ChangeOwnerAndReturnTraverser(newTree.symbol, impl)(newTree setSymbol impl) - } - - /** Add mixin constructor definition - * def $init$(): Unit = () - * to `stats` unless there is already one. - */ - private def addMixinConstructorDef(clazz: Symbol, stats: List[Tree]): List[Tree] = - if (treeInfo.firstConstructor(stats) != EmptyTree) stats - else DefDef(clazz.primaryConstructor, Block(List(), Literal(Constant(())))) :: stats - - private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) { - val templ1 = ( - Template(templ.parents, noSelfType, addMixinConstructorDef(clazz, templ.body map deriveMemberForImplClass)) - setSymbol clazz.newLocalDummy(templ.pos) - ) - templ1.changeOwner(templ.symbol.owner -> clazz, templ.symbol -> templ1.symbol) - templ1 - } - - def implClassDefs(trees: List[Tree]): List[Tree] = { - trees collect { - case cd: ClassDef if cd.symbol.needsImplClass => - val clazz = implClass(cd.symbol).initialize - ClassDef(clazz, implTemplate(clazz, cd.impl)) - } + private def mkAssign(clazz: Symbol, assignSym: Symbol, rhs: Tree): Tree = { + val qual = Select(This(clazz), assignSym) + if (assignSym.isSetter) Apply(qual, List(rhs)) + else Assign(qual, rhs) } /** Add calls to supermixin constructors @@ -304,15 +62,16 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => * to tree, which is assumed to be the body of a constructor of class clazz. */ private def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = { - def mixinConstructorCall(impl: Symbol): Tree = atPos(tree.pos) { - Apply(Select(This(clazz), impl.primaryConstructor), List()) + def mixinConstructorCall(mc: Symbol): Tree = atPos(tree.pos) { + Apply(SuperSelect(clazz, mc.primaryConstructor), Nil) } val mixinConstructorCalls: List[Tree] = { for (mc <- clazz.mixinClasses.reverse - if mc.hasFlag(lateINTERFACE)) - yield mixinConstructorCall(implClass(mc)) + if mc.isTrait && mc.primaryConstructor != NoSymbol) + yield mixinConstructorCall(mc) } tree match { + case Block(Nil, expr) => // AnyVal constructor - have to provide a real body so the // jvm doesn't throw a VerifyError. But we can't add the @@ -329,42 +88,14 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } protected val mixinTransformer = new Transformer { - override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = - (super.transformStats(stats, exprOwner) ::: - super.transformStats(implClassDefs(stats), exprOwner)) override def transform(tree: Tree): Tree = { val sym = tree.symbol val tree1 = tree match { - case ClassDef(mods, _, _, impl) if sym.needsImplClass => - implClass(sym).initialize // to force lateDEFERRED flags - copyClassDef(tree)(mods = mods | INTERFACE, impl = ifaceTemplate(impl)) case DefDef(_,_,_,_,_,_) if sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass => deriveDefDef(tree)(addMixinConstructorCalls(_, sym.owner)) // (3) case Template(parents, self, body) => val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos) treeCopy.Template(tree, parents1, noSelfType, body) - case This(_) if sym.needsImplClass => - val impl = implClass(sym) - var owner = currentOwner - while (owner != sym && owner != impl) owner = owner.owner; - if (owner == impl) This(impl) setPos tree.pos - else tree - //TODO what about this commented out code? -/* !!! - case Super(qual, mix) => - val mix1 = mix - if (mix == tpnme.EMPTY) mix - else { - val ps = enteringErasure { - sym.info.parents dropWhile (p => p.symbol.name != mix) - } - assert(!ps.isEmpty, tree); - if (ps.head.symbol.needsImplClass) implClass(ps.head.symbol).name - else mix - } - if (sym.needsImplClass) Super(implClass(sym), mix1) setPos tree.pos - else treeCopy.Super(tree, qual, mix1) -*/ case _ => tree } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index aef2817db7..1e479d3f63 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -73,7 +73,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { override def transform(tree: Tree): Tree = { tree match { - case cd @ ClassDef(mods0, name0, tparams0, impl0) if !cd.symbol.isInterface && !isPrimitiveValueClass(cd.symbol) => + case cd @ ClassDef(mods0, name0, tparams0, impl0) if !isPrimitiveValueClass(cd.symbol) && cd.symbol.primaryConstructor != NoSymbol => if(cd.symbol eq AnyValClass) { cd } @@ -305,7 +305,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { val delayedHook = delayedEndpointDef(remainingConstrStats) val delayedHookSym = delayedHook.symbol.asInstanceOf[MethodSymbol] - // transform to make the closure-class' default constructor assign the the outer instance to its param-accessor field. + // transform to make the closure-class' default constructor assign the outer instance to its param-accessor field. val hookCallerClass = (new ConstructorTransformer(unit)) transform delayedInitClosure(delayedHookSym) val delayedInitCall = localTyper.typedPos(impl.pos) { gen.mkMethodCall(This(clazz), delayedInitMethod, Nil, List(New(hookCallerClass.symbol.tpe, This(clazz)))) @@ -456,7 +456,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { // find and dissect primary constructor private val (primaryConstr, _primaryConstrParams, primaryConstrBody) = stats collectFirst { - case dd@DefDef(_, _, _, vps :: Nil, _, rhs: Block) if dd.symbol.isPrimaryConstructor => (dd, vps map (_.symbol), rhs) + case dd@DefDef(_, _, _, vps :: Nil, _, rhs: Block) if dd.symbol.isPrimaryConstructor || dd.symbol.isMixinConstructor => (dd, vps map (_.symbol), rhs) } getOrElse { abort("no constructor in template: impl = " + impl) } @@ -517,9 +517,11 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { case Apply(Select(This(_), _), List()) => // references to parameter accessor methods of own class become references to parameters // outer accessors become references to $outer parameter - if (canBeSupplanted(tree.symbol)) + if (clazz.isTrait) + super.transform(tree) + else if (canBeSupplanted(tree.symbol)) gen.mkAttributedIdent(parameter(tree.symbol.accessed)) setPos tree.pos - else if (tree.symbol.outerSource == clazz && !clazz.isImplClass) + else if (tree.symbol.outerSource == clazz) gen.mkAttributedIdent(parameterNamed(nme.OUTER)) setPos tree.pos else super.transform(tree) @@ -566,7 +568,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { } // Constant typed vals are not memoized. - def memoizeValue(sym: Symbol) = !sym.info.isInstanceOf[ConstantType] + def memoizeValue(sym: Symbol) = !sym.info.resultType.isInstanceOf[ConstantType] /** Triage definitions and statements in this template into the following categories. * The primary constructor is treated separately, as it is assembled in part from these pieces. @@ -587,7 +589,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { for (stat <- primaryConstrBody.stats) { constrStatBuf += stat stat match { - case ValDef(mods, name, _, _) if mods hasFlag PRESUPER => + case ValDef(mods, name, _, _) if mods.hasFlag(PRESUPER) => // stat is the constructor-local definition of the field value val fields = presupers filter (_.getterName == name) assert(fields.length == 1, s"expected exactly one field by name $name in $presupers of $clazz's early initializers") @@ -624,12 +626,12 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { stat match { // recurse on class definition, store in defBuf - case _: ClassDef => defBuf += new ConstructorTransformer(unit).transform(stat) + case _: ClassDef if !stat.symbol.isInterface => defBuf += new ConstructorTransformer(unit).transform(stat) // Triage methods -- they all end up in the template -- // regular ones go to `defBuf`, secondary contructors go to `auxConstructorBuf`. // The primary constructor is dealt with separately (we're massaging it here). - case _: DefDef if statSym.isPrimaryConstructor => () + case _: DefDef if statSym.isPrimaryConstructor || statSym.isMixinConstructor => () case _: DefDef if statSym.isConstructor => auxConstructorBuf += stat case _: DefDef => defBuf += stat diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 5d93f9f20e..67e3f67f2f 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -8,7 +8,7 @@ import scala.collection.mutable.LinkedHashMap /** * This transformer is responsible for preparing lambdas for runtime, by either translating to anonymous classes - * or to a tree that will be convereted to invokedynamic by the JVM 1.8+ backend. + * or to a tree that will be converted to invokedynamic by the JVM 1.8+ backend. * * The main assumption it makes is that a lambda {args => body} has been turned into * {args => liftedBody()} where lifted body is a top level method that implements the body of the lambda. @@ -260,7 +260,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val body = Block( List( - Apply(Select(Super(gen.mkAttributedThis(newClass), tpnme.EMPTY) setPos newClass.pos, nme.CONSTRUCTOR) setPos newClass.pos, Nil) setPos newClass.pos + atPos(newClass.pos)(Apply(gen.mkSuperInitCall, Nil)) ) ++ assigns, Literal(Constant(())): Tree ) setPos newClass.pos diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 0e44751a3f..41f22e5669 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -662,7 +662,7 @@ abstract class Erasure extends AddInterfaces adaptMember(selectFrom(applied)) } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) { assert(tree.symbol.owner != ArrayClass) - selectFrom(cast(qual1, tree.symbol.owner.tpe)) + selectFrom(cast(qual1, tree.symbol.owner.tpe.resultType)) } else { selectFrom(qual1) } @@ -1103,7 +1103,6 @@ abstract class Erasure extends AddInterfaces } } else tree case Template(parents, self, body) => - assert(!currentOwner.isImplClass) //Console.println("checking no dble defs " + tree)//DEBUG checkNoDoubleDefs(tree.symbol.owner) treeCopy.Template(tree, parents, noSelfType, addBridges(body, currentOwner)) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 4abcc774da..3d6fad4238 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -210,7 +210,7 @@ abstract class ExplicitOuter extends InfoTransform // class needs to have a common naming scheme, independently of whether // the field was accessed from an inner class or not. See #2946 if (sym.owner.isTrait && sym.isLocalToThis && - (sym.getterIn(sym.owner.toInterface) == NoSymbol)) + (sym.getterIn(sym.owner) == NoSymbol)) sym.makeNotPrivate(sym.owner) tp } @@ -241,12 +241,17 @@ abstract class ExplicitOuter extends InfoTransform * Will return `EmptyTree` if there is no outer accessor because of a premature self reference. */ private def outerSelect(base: Tree): Tree = { - val baseSym = base.tpe.typeSymbol.toInterface + val baseSym = base.tpe.typeSymbol val outerAcc = outerAccessor(baseSym) - if (outerAcc == NoSymbol && baseSym.ownersIterator.exists(isUnderConstruction)) { - // e.g neg/t6666.scala - // The caller will report the error with more information. - EmptyTree + if (outerAcc == NoSymbol) { + if (baseSym.ownersIterator.exists(isUnderConstruction)) { + // e.g neg/t6666.scala + // The caller will report the error with more information. + EmptyTree + } else { + globalError(currentOwner.pos, s"Internal error: unable to find the outer accessor symbol of $baseSym") + EmptyTree + } } else { val currentClass = this.currentClass //todo: !!! if this line is removed, we get a build failure that protected$currentClass need an override modifier // outerFld is the $outer field of the current class, if the reference can @@ -254,6 +259,7 @@ abstract class ExplicitOuter extends InfoTransform // otherwise it is NoSymbol val outerFld = if (outerAcc.owner == currentClass && + !outerAcc.owner.isTrait && base.tpe =:= currentClass.thisType && outerAcc.owner.isEffectivelyFinal) outerField(currentClass) suchThat (_.owner == currentClass) @@ -274,8 +280,7 @@ abstract class ExplicitOuter extends InfoTransform */ protected def outerPath(base: Tree, from: Symbol, to: Symbol): Tree = { //Console.println("outerPath from "+from+" to "+to+" at "+base+":"+base.tpe) - //assert(base.tpe.widen.baseType(from.toInterface) != NoType, ""+base.tpe.widen+" "+from.toInterface)//DEBUG - if (from == to || from.isImplClass && from.toInterface == to) base + if (from == to) base else outerPath(outerSelect(base), from.outerClass, to) } @@ -400,7 +405,7 @@ abstract class ExplicitOuter extends InfoTransform case Template(parents, self, decls) => val newDefs = new ListBuffer[Tree] atOwner(tree, currentOwner) { - if (!currentClass.isInterface || (currentClass hasFlag lateINTERFACE)) { + if (!currentClass.isInterface) { if (isInner(currentClass)) { if (hasOuterField(currentClass)) newDefs += outerFieldDef // (1a) @@ -479,7 +484,7 @@ abstract class ExplicitOuter extends InfoTransform // base.<outer>.eq(o) --> base.$outer().eq(o) if there's an accessor, else the whole tree becomes TRUE // TODO remove the synthetic `<outer>` method from outerFor?? case Apply(eqsel@Select(eqapp@Apply(sel@Select(base, nme.OUTER_SYNTH), Nil), eq), args) => - val outerFor = sel.symbol.owner.toInterface // TODO: toInterface necessary? + val outerFor = sel.symbol.owner val acc = outerAccessor(outerFor) if (acc == NoSymbol || diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index fbb0307773..0db9f19597 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -41,8 +41,6 @@ abstract class Flatten extends InfoTransform { } 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 diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index a372136781..7a5bd747c4 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -98,11 +98,6 @@ abstract class LambdaLift extends InfoTransform { */ private val proxyNames = mutable.HashMap[Symbol, Name]() - // (trait, name) -> owner - private val localTraits = mutable.HashMap[(Symbol, Name), Symbol]() - // (owner, name) -> implClass - private val localImplClasses = mutable.HashMap[(Symbol, Name), Symbol]() - /** A flag to indicate whether new free variables have been found */ private var changedFreeVars: Boolean = _ @@ -176,24 +171,7 @@ abstract class LambdaLift extends InfoTransform { case ClassDef(_, _, _, _) => liftedDefs(tree.symbol) = Nil if (sym.isLocalToBlock) { - // Don't rename implementation classes independently of their interfaces. If - // the interface is to be renamed, then we will rename the implementation - // class at that time. You'd think we could call ".implClass" on the trait - // rather than collecting them in another map, but that seems to fail for - // exactly the traits being renamed here (i.e. defined in methods.) - // - // !!! - it makes no sense to have methods like "implClass" and - // "companionClass" which fail for an arbitrary subset of nesting - // arrangements, and then have separate methods which attempt to compensate - // for that failure. There should be exactly one method for any given - // entity which always gives the right answer. - if (sym.isImplClass) - localImplClasses((sym.owner, tpnme.interfaceName(sym.name))) = sym - else { - renamable += sym - if (sym.isTrait) - localTraits((sym, sym.name)) = sym.owner - } + renamable += sym } case DefDef(_, _, _, _, _, _) => if (sym.isLocalToBlock) { @@ -264,40 +242,18 @@ abstract class LambdaLift extends InfoTransform { // Generating a unique name, mangled with the enclosing full class name (including // package - subclass might have the same name), avoids a VerifyError in the case // that a sub-class happens to lifts out a method with the *same* name. - if (originalName.isTermName && !sym.enclClass.isImplClass && calledFromInner(sym)) + if (originalName.isTermName && calledFromInner(sym)) newTermNameCached(nonAnon(sym.enclClass.fullName('$')) + nme.EXPAND_SEPARATOR_STRING + name) else name } } - /* Rename a trait's interface and implementation class in coordinated fashion. */ - def renameTrait(traitSym: Symbol, implSym: Symbol) { - val originalImplName = implSym.name - renameSym(traitSym) - implSym setName tpnme.implClassName(traitSym.name) - - debuglog("renaming impl class in step with %s: %s => %s".format(traitSym, originalImplName, implSym.name)) - } - val allFree: Set[Symbol] = free.values.flatMap(_.iterator).toSet for (sym <- renamable) { - // If we renamed a trait from Foo to Foo$1, we must rename the implementation - // class from Foo$class to Foo$1$class. (Without special consideration it would - // become Foo$class$1 instead.) Since the symbols are being renamed out from - // under us, and there's no reliable link between trait symbol and impl symbol, - // we have maps from ((trait, name)) -> owner and ((owner, name)) -> impl. - localTraits remove ((sym, sym.name)) match { - case None => - if (allFree(sym)) proxyNames(sym) = newName(sym) - else renameSym(sym) - case Some(owner) => - localImplClasses remove ((owner, sym.name)) match { - case Some(implSym) => renameTrait(sym, implSym) - case _ => renameSym(sym) // pure interface, no impl class - } - } + if (allFree(sym)) proxyNames(sym) = newName(sym) + else renameSym(sym) } afterOwnPhase { @@ -456,7 +412,6 @@ abstract class LambdaLift extends InfoTransform { } sym.owner = sym.owner.enclClass - if (sym.isClass) sym.owner = sym.owner.toInterface if (sym.isMethod) sym setFlag LIFTED liftedDefs(sym.owner) ::= tree // TODO: this modifies the ClassInfotype of the enclosing class, which is associated with another phase (explicitouter). diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index d13e11e9ec..ed7ef0d8fd 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -32,8 +32,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // --------- helper functions ----------------------------------------------- /** 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 + * mixin transform is RHS of the method body (destined to be in a interface default method) + * + * To be statically implemented, a member must be a method that belonged to the trait's implementation class * 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 @@ -43,33 +44,18 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * methods in the impl class (because they can have arbitrary initializers) */ private def isImplementedStatically(sym: Symbol) = ( - sym.owner.isImplClass + sym.isMethod + && (!sym.hasFlag(DEFERRED | SUPERACCESSOR) || (sym hasFlag lateDEFERRED)) + && sym.owner.isTrait && sym.isMethod && (!sym.isModule || sym.hasFlag(PRIVATE | LIFTED)) && (!(sym hasFlag (ACCESSOR | SUPERACCESSOR)) || sym.isLazy) + && !sym.isPrivate + && !sym.hasAllFlags(LIFTED | MODULE | METHOD) + && !sym.isConstructor + && (!sym.hasFlag(notPRIVATE | LIFTED) || sym.hasFlag(ACCESSOR | SUPERACCESSOR | MODULE)) ) - /** A member of a trait is static only if it belongs only to the - * implementation class, not the interface, and it is implemented - * statically. - */ - private def isStaticOnly(sym: Symbol) = - isImplementedStatically(sym) && sym.isImplOnly - - /** A member of a trait is forwarded if it is implemented statically and it - * is also visible in the trait's interface. In that case, a forwarder to - * the member's static implementation will be added to the class that - * inherits the trait. - */ - private def isForwarded(sym: Symbol) = - isImplementedStatically(sym) && !sym.isImplOnly - - /** Maps the type of an implementation class to its interface; - * maps all other types to themselves. - */ - private def toInterface(tp: Type): Type = - enteringMixin(tp.typeSymbol.toInterface).tpe - private def isFieldWithBitmap(field: Symbol) = { field.info // ensure that nested objects are transformed // For checkinit consider normal value getters @@ -97,22 +83,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { && !(sym.accessed hasAnnotation TransientAttr) ) - /** Maps all parts of this type that refer to implementation classes to - * their corresponding interfaces. - */ - private val toInterfaceMap = new TypeMap { - def apply(tp: Type): Type = mapOver( tp match { - case TypeRef(pre, sym, args) if sym.isImplClass => - typeRef(pre, enteringMixin(sym.toInterface), args) - case _ => tp - }) - } - - /** The implementation class corresponding to a currently compiled interface. - * todo: try to use Symbol.implClass instead? - */ - private def implClass(iface: Symbol) = iface.implClass orElse (erasure implClass iface) - /** Returns the symbol that is accessed by a super-accessor in a mixin composition. * * @param base The class in which everything is mixed together @@ -159,8 +129,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** Add given member to given class, and mark member as mixed-in. */ def addMember(clazz: Symbol, member: Symbol): Symbol = { - debuglog("new member of " + clazz + ":" + member.defString) - clazz.info.decls enter member setFlag MIXEDIN + debuglog(s"mixing into $clazz: ${member.defString}") + clazz.info.decls enter member setFlag MIXEDIN resetFlag JAVA_DEFAULTMETHOD } def cloneAndAddMember(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol = addMember(clazz, cloneBeforeErasure(mixinClass, mixinMember, clazz)) @@ -227,12 +197,11 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } clazz.info // make sure info is up to date, so that implClass is set. - val impl = implClass(clazz) orElse abort("No impl class for " + clazz) - for (member <- impl.info.decls) { + for (member <- clazz.info.decls) { if (!member.isMethod && !member.isModule && !member.isModuleVar) { assert(member.isTerm && !member.isDeferred, member) - if (member.getterIn(impl).isPrivate) { + if (member.getterIn(clazz).isPrivate) { member.makeNotPrivate(clazz) // this will also make getter&setter not private } val getter = member.getterIn(clazz) @@ -241,6 +210,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val setter = member.setterIn(clazz) if (setter == NoSymbol) addMember(clazz, newSetter(member)) } + clazz.info.decls.unlink(member) } } debuglog("new defs of " + clazz + " = " + clazz.info.decls) @@ -266,16 +236,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { ) /* Mix in members of implementation class mixinClass into class clazz */ - def mixinImplClassMembers(mixinClass: Symbol, mixinInterface: Symbol) { - if (!mixinClass.isImplClass) devWarning ("Impl class flag is not set " + - ((mixinClass.debugLocationString, mixinInterface.debugLocationString))) - - for (member <- mixinClass.info.decls ; if isForwarded(member)) { - val imember = member overriddenSymbol mixinInterface - imember overridingSymbol clazz match { + def mixinTraitForwarders(mixinClass: Symbol) { + for (member <- mixinClass.info.decls ; if isImplementedStatically(member)) { + member overridingSymbol clazz match { case NoSymbol => - if (clazz.info.findMember(member.name, 0, lateDEFERRED, stableOnly = false).alternatives contains imember) - cloneAndAddMixinMember(mixinInterface, imember).asInstanceOf[TermSymbol] setAlias member + if (clazz.info.findMember(member.name, 0, 0L, stableOnly = false).alternatives contains member) + cloneAndAddMixinMember(mixinClass, member).asInstanceOf[TermSymbol] setAlias member case _ => } } @@ -296,7 +262,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val mixedInAccessor = cloneAndAddMixinMember(mixinClass, mixinMember) if (mixinMember.isLazy) { initializer(mixedInAccessor) = ( - implClass(mixinClass).info.decl(mixinMember.name) + mixinClass.info.decl(mixinMember.name) orElse abort("Could not find initializer for " + mixinMember.name) ) } @@ -358,67 +324,16 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // first complete the superclass with mixed in members addMixedinMembers(clazz.superClass, unit) - for (mc <- clazz.mixinClasses ; if mc hasFlag lateINTERFACE) { + for (mc <- clazz.mixinClasses ; if mc.isTrait) { // @SEAN: adding trait tracking so we don't have to recompile transitive closures unit.depends += mc addLateInterfaceMembers(mc) mixinTraitMembers(mc) - mixinImplClassMembers(implClass(mc), mc) + mixinTraitForwarders(mc) } } - /** The info transform for this phase does the following: - * - The parents of every class are mapped from implementation class to interface - * - Implementation classes become modules that inherit nothing - * and that define all. - */ - override def transformInfo(sym: Symbol, tp: Type): Type = tp match { - case ClassInfoType(parents, decls, clazz) => - var parents1 = parents - var decls1 = decls - if (!clazz.isPackageClass) { - exitingMixin(clazz.owner.info) - if (clazz.isImplClass) { - clazz setFlag lateMODULE - var sourceModule = clazz.owner.info.decls.lookup(sym.name.toTermName) - if (sourceModule == NoSymbol) { - sourceModule = ( - clazz.owner.newModuleSymbol(sym.name.toTermName, sym.pos, MODULE) - setModuleClass sym.asInstanceOf[ClassSymbol] - ) - clazz.owner.info.decls enter sourceModule - } - else { - sourceModule setPos sym.pos - if (sourceModule.flags != MODULE) { - log(s"!!! Directly setting sourceModule flags for $sourceModule from ${sourceModule.flagString} to MODULE") - sourceModule.flags = MODULE - } - } - sourceModule setInfo sym.tpe - // Companion module isn't visible for anonymous class at this point anyway - assert(clazz.sourceModule != NoSymbol || clazz.isAnonymousClass, s"$clazz has no sourceModule: $sym ${sym.tpe}") - parents1 = List() - decls1 = newScopeWith(decls.toList filter isImplementedStatically: _*) - } else if (!parents.isEmpty) { - parents1 = parents.head :: (parents.tail map toInterface) - } - } - //decls1 = enteringPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug - if ((parents1 eq parents) && (decls1 eq decls)) tp - else ClassInfoType(parents1, decls1, clazz) - - case MethodType(params, restp) => - toInterfaceMap( - if (isImplementedStatically(sym)) { - val ownerParam = sym.newSyntheticValueParam(toInterface(sym.owner.typeOfThis)) - MethodType(ownerParam :: params, restp) - } else - tp) - - case _ => - tp - } + override def transformInfo(sym: Symbol, tp: Type): Type = tp /** Return a map of single-use fields to the lazy value that uses them during initialization. * Each field has to be private and defined in the enclosing class, and there must @@ -466,10 +381,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { new MixinTransformer(unit) class MixinTransformer(unit : CompilationUnit) extends Transformer { - /** Within a static implementation method: the parameter referring to the - * current object. Undefined everywhere else. - */ - private var self: Symbol = _ /** The rootContext used for typing */ private val rootContext = @@ -505,15 +416,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * (that is, every node is processed before its children). * What transform does: * - For every non-trait class, add all mixed in members to the class info. - * - For every trait, add all late interface members to the class info - * - For every static implementation method: - * - remove override flag - * - create a new method definition that also has a `self` parameter - * (which comes first) Iuli: this position is assumed by tail call elimination - * on a different receiver. Storing a new 'this' assumes it is located at - * index 0 in the local variable table. See 'STORE_THIS' and GenASM. - * - Map implementation class types in type-apply's to their interfaces - * - Remove all fields in implementation classes */ private def preTransform(tree: Tree): Tree = { val sym = tree.symbol @@ -524,87 +426,19 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { if (!currentOwner.isTrait && !isPrimitiveValueClass(currentOwner)) addMixedinMembers(currentOwner, unit) - else if (currentOwner hasFlag lateINTERFACE) + else if (currentOwner.isTrait) addLateInterfaceMembers(currentOwner) tree - case DefDef(_, _, _, vparams :: Nil, _, _) => - if (currentOwner.isImplClass) { - if (isImplementedStatically(sym)) { - sym setFlag notOVERRIDE - self = sym.newValueParameter(nme.SELF, sym.pos) setInfo toInterface(currentOwner.typeOfThis) - val selfdef = ValDef(self) setType NoType - copyDefDef(tree)(vparamss = List(selfdef :: vparams)) - } - else EmptyTree - } - else { - if (currentOwner.isTrait && sym.isSetter && !enteringPickler(sym.isDeferred)) { - sym.addAnnotation(TraitSetterAnnotationClass) - } - tree - } - // !!! What is this doing, and why is it only looking for exactly - // one type parameter? It would seem to be - // "Map implementation class types in type-apply's to their interfaces" - // from the comment on preTransform, but is there some way we should know - // that impl class types in type applies can only appear in single - // type parameter type constructors? - case Apply(tapp @ TypeApply(fn, List(arg)), List()) => - if (arg.tpe.typeSymbol.isImplClass) { - val ifacetpe = toInterface(arg.tpe) - arg setType ifacetpe - tapp setType MethodType(Nil, ifacetpe) - tree setType ifacetpe - } - tree - case ValDef(_, _, _, _) if currentOwner.isImplClass => - EmptyTree + case _ => + if (currentOwner.isTrait && sym.isSetter && !enteringPickler(sym.isDeferred)) { + sym.addAnnotation(TraitSetterAnnotationClass) + } tree } } - /** Create an identifier which references self parameter. - */ - private def selfRef(pos: Position) = - gen.mkAttributedIdent(self) setPos pos - - /** Replace a super reference by this or the self parameter, depending - * on whether we are in an implementation class or not. - * Leave all other trees unchanged. - */ - private def transformSuper(tree: Tree) = tree match { - case Super(qual, _) => - transformThis(qual) - case _ => - tree - } - - /** Replace a this reference to the current implementation class by the self - * parameter. Leave all other trees unchanged. - */ - private def transformThis(tree: Tree) = tree match { - case This(_) if tree.symbol.isImplClass => - assert(tree.symbol == currentOwner.enclClass) - selfRef(tree.pos) - case _ => - tree - } - - /** Create a static reference to given symbol `sym` of the - * form `M.sym` where M is the symbol's implementation module. - */ - private def staticRef(sym: Symbol): Tree = { - sym.owner.info //todo: needed? - sym.owner.owner.info //todo: needed? - - if (sym.owner.sourceModule eq NoSymbol) - abort(s"Cannot create static reference to $sym because ${sym.safeOwner} has no source module") - else - REF(sym.owner.sourceModule) DOT sym - } - def needsInitAndHasOffset(sym: Symbol) = needsInitFlag(sym) && (fieldOffset contains sym) @@ -643,6 +477,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * - A super accessor for every super accessor in a mixin class * - Forwarders for all methods that are implemented statically * All superaccessors are completed with right-hand sides (@see completeSuperAccessor) + * * @param clazz The class to which definitions are added */ private def addNewDefs(clazz: Symbol, stats: List[Tree]): List[Tree] = { @@ -700,7 +535,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ def completeSuperAccessor(stat: Tree) = stat match { case DefDef(_, _, _, vparams :: Nil, _, EmptyTree) if stat.symbol.isSuperAccessor => - val body = atPos(stat.pos)(Apply(Select(Super(clazz, tpnme.EMPTY), stat.symbol.alias), vparams map (v => Ident(v.symbol)))) + val body = atPos(stat.pos)(Apply(SuperSelect(clazz, stat.symbol.alias), vparams map (v => Ident(v.symbol)))) val pt = stat.symbol.tpe.resultType copyDefDef(stat)(rhs = enteringMixin(transform(localTyper.typed(body, pt)))) @@ -887,7 +722,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def isUnit = sym.tpe.resultType.typeSymbol == UnitClass def isEmpty = stat.rhs == EmptyTree - if (sym.isLazy && !isEmpty && !clazz.isImplClass) { + if (!clazz.isTrait && sym.isLazy && !isEmpty) { assert(fieldOffset contains sym, sym) deriveDefDef(stat) { case t if isUnit => mkLazyDef(clazz, sym, List(t), UNIT, fieldOffset(sym)) @@ -898,7 +733,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { case t => t // pass specialized lazy vals through } } - else if (needsInitFlag(sym) && !isEmpty && !clazz.hasFlag(IMPLCLASS | TRAIT)) { + else if (needsInitFlag(sym) && !isEmpty && !clazz.hasFlag(TRAIT)) { assert(fieldOffset contains sym, sym) deriveDefDef(stat)(rhs => (mkCheckedAccessor(clazz, _: Tree, fieldOffset(sym), stat.pos, sym))( @@ -992,7 +827,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // if it is a mixed-in lazy value, complete the accessor if (getter.isLazy) { val isUnit = isUnitGetter(getter) - val initCall = Apply(staticRef(initializer(getter)), gen.mkAttributedThis(clazz) :: Nil) + val initCall = Apply(SuperSelect(clazz, initializer(getter)), Nil) val selection = fieldAccess(getter) val init = if (isUnit) initCall else atPos(getter.pos)(Assign(selection, initCall)) val returns = if (isUnit) UNIT else selection @@ -1040,12 +875,11 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // for all symbols `sym` in the class definition, which are mixed in: for (sym <- clazz.info.decls ; if sym hasFlag MIXEDIN) { - // if current class is a trait interface, add an abstract method for accessor `sym` - if (clazz hasFlag lateINTERFACE) { + // if current class is a trait, add an abstract method for accessor `sym` + if (clazz.isTrait) { addDefDef(sym) - } - // if class is not a trait add accessor definitions - else if (!clazz.isTrait) { + } else { + // if class is not a trait add accessor definitions if (isConcreteAccessor(sym)) { // add accessor definitions addDefDef(sym, { @@ -1072,13 +906,20 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } else { // add forwarders - assert(sym.alias != NoSymbol, sym) + assert(sym.alias != NoSymbol, (sym, sym.debugFlagString, clazz)) // debuglog("New forwarder: " + sym.defString + " => " + sym.alias.defString) - if (!sym.isMacro) addDefDef(sym, Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: sym.paramss.head.map(Ident))) + if (!sym.isMacro) addDefDef(sym, Apply(SuperSelect(clazz, sym.alias), sym.paramss.head.map(Ident(_)))) } } } stats1 = add(stats1, newDefs.toList) + if (clazz.isTrait) stats1 = + stats1.filter { + case vd: ValDef => + // TODO do we get here? + false + case _ => true + } if (!clazz.isTrait) stats1 = stats1 map completeSuperAccessor stats1 } @@ -1113,14 +954,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * - refer to fields in some implementation class via an abstract method in the interface. */ private def postTransform(tree: Tree): Tree = { - def siteWithinImplClass = currentOwner.enclClass.isImplClass val sym = tree.symbol - // change every node type that refers to an implementation class to its - // corresponding interface, unless the node's symbol is an implementation class. - if (tree.tpe.typeSymbol.isImplClass && ((sym eq null) || !sym.isImplClass)) - tree modifyType toInterface - tree match { case templ @ Template(parents, self, body) => // change parents of templates to conform to parents in the symbol info @@ -1130,87 +965,21 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // add all new definitions to current class or interface treeCopy.Template(tree, parents1, self, addNewDefs(currentOwner, body)) - // remove widening casts - case Apply(TypeApply(Select(qual, _), targ :: _), _) if isCastSymbol(sym) && (qual.tpe <:< targ.tpe) => - qual - - case Apply(Select(qual, _), args) => - /* Changes `qual.m(args)` where m refers to an implementation - * class method to Q.m(S, args) where Q is the implementation module of - * `m` and S is the self parameter for the call, which - * is determined as follows: - * - if qual != super, qual itself - * - if qual == super, and we are in an implementation class, - * the current self parameter. - * - if qual == super, and we are not in an implementation class, `this` - */ - def staticCall(target: Symbol) = { - def implSym = implClass(sym.owner).info.member(sym.name) - assert(target ne NoSymbol, - List(sym + ":", sym.tpe, sym.owner, implClass(sym.owner), implSym, - enteringPrevPhase(implSym.tpe), phase) mkString " " - ) - typedPos(tree.pos)(Apply(staticRef(target), transformSuper(qual) :: args)) - } - - if (isStaticOnly(sym)) { - // change calls to methods which are defined only in implementation - // classes to static calls of methods in implementation modules - staticCall(sym) - } - else qual match { - case Super(_, mix) => - // change super calls to methods in implementation classes to static calls. - // Transform references super.m(args) as follows: - // - if `m` refers to a trait, insert a static call to the corresponding static - // implementation - // - otherwise return tree unchanged - assert( - !(mix == tpnme.EMPTY && siteWithinImplClass), - "illegal super in trait: " + currentOwner.enclClass + " " + tree - ) + case Select(qual, name) if sym.owner.isTrait && !sym.isMethod => + // refer to fields in some trait an abstract getter in the interface. + val ifaceGetter = sym getterIn sym.owner - if (sym.owner hasFlag lateINTERFACE) { - if (sym.hasAccessorFlag) { - assert(args.isEmpty, args) - val sym1 = sym.overridingSymbol(currentOwner.enclClass) - typedPos(tree.pos)((transformSuper(qual) DOT sym1)()) - } - else { - staticCall(enteringPrevPhase(sym.overridingSymbol(implClass(sym.owner)))) - } - } - else { - assert(!siteWithinImplClass, currentOwner.enclClass) - tree - } - case _ => - tree - } - - case This(_) => - transformThis(tree) - - case Select(Super(_, _), name) => - tree - - case Select(qual, name) if sym.owner.isImplClass && !isStaticOnly(sym) => - assert(!sym.isMethod, "no method allowed here: %s%s %s".format(sym, sym.isImplOnly, sym.flagString)) - // refer to fields in some implementation class via an abstract - // getter in the interface. - val iface = toInterface(sym.owner.tpe).typeSymbol - val ifaceGetter = sym getterIn iface - - if (ifaceGetter == NoSymbol) abort("No getter for " + sym + " in " + iface) + if (ifaceGetter == NoSymbol) abort("No getter for " + sym + " in " + sym.owner) else typedPos(tree.pos)((qual DOT ifaceGetter)()) case Assign(Apply(lhs @ Select(qual, _), List()), rhs) => - // assign to fields in some implementation class via an abstract - // setter in the interface. - def setter = lhs.symbol.setterIn(toInterface(lhs.symbol.owner.tpe).typeSymbol) setPos lhs.pos + // assign to fields in some trait via an abstract setter in the interface. + // Note that the case above has added the empty application. + val setter = lhs.symbol.setterIn(lhs.symbol.owner.tpe.typeSymbol) setPos lhs.pos typedPos(tree.pos)((qual DOT setter)(rhs)) + case _ => tree } diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 16ea3ea90f..fa7c503213 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -69,7 +69,7 @@ abstract class TailCalls extends Transform { * are optimized. Since 'this' is not a local variable, a dummy local val * is added and used as a label parameter. The backend knows to load * the corresponding argument in the 'this' (local at index 0). This dummy local - * is never used and should be cleand up by dead code elimination (when enabled). + * is never used and should be cleaned up by dead code elimination (when enabled). * </p> * <p> * This phase has been moved before pattern matching to catch more diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index eea1f53cbc..40a988ee94 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -374,8 +374,9 @@ abstract class UnCurry extends InfoTransform */ private def replaceElidableTree(tree: Tree): Tree = { tree match { - case DefDef(_,_,_,_,_,_) => - deriveDefDef(tree)(rhs => Block(Nil, gen.mkZero(rhs.tpe)) setType rhs.tpe) setSymbol tree.symbol setType tree.tpe + case DefDef(_,_,_,_,_,rhs) => + val rhs1 = if (rhs == EmptyTree) rhs else Block(Nil, gen.mkZero(rhs.tpe)) setType rhs.tpe + deriveDefDef(tree)(_ => rhs1) setSymbol tree.symbol setType tree.tpe case _ => gen.mkZero(tree.tpe) setType tree.tpe } @@ -744,7 +745,7 @@ abstract class UnCurry extends InfoTransform case Packed(param, tempVal) => (param, tempVal) }.unzip - val rhs1 = if (tempVals.isEmpty) rhs else { + val rhs1 = if (rhs == EmptyTree || tempVals.isEmpty) rhs else { localTyper.typedPos(rhs.pos) { // Patch the method body to refer to the temp vals val rhsSubstituted = rhs.substituteSymbols(packedParams map (_.symbol), tempVals map (_.symbol)) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala index b2f2516b5b..05f2d60be1 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala @@ -222,7 +222,7 @@ trait Interface extends ast.TreeDSL { object substIdentsForTrees extends Transformer { private def typedIfOrigTyped(to: Tree, origTp: Type): Tree = if (origTp == null || origTp == NoType) to - // important: only type when actually substing and when original tree was typed + // important: only type when actually substituting and when original tree was typed // (don't need to use origTp as the expected type, though, and can't always do this anyway due to unknown type params stemming from polymorphic extractors) else typer.typed(to) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index cb4eab335b..c5a3d605b1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -723,7 +723,6 @@ trait Contexts { self: Analyzer => ( (ab.isTerm || ab == rootMirror.RootClass) || (accessWithin(ab) || accessWithinLinked(ab)) && ( !sym.isLocalToThis - || sym.owner.isImplClass // allow private local accesses to impl classes || sym.isProtected && isSubThisType(pre, sym.owner) || pre =:= sym.owner.thisType ) @@ -978,7 +977,7 @@ trait Contexts { self: Analyzer => */ def isInPackageObject(sym: Symbol, pkg: Symbol): Boolean = { if (sym.isOverloaded) sym.alternatives.exists(alt => isInPackageObject(alt, pkg)) - else pkg.isPackage && sym.owner != pkg && requiresQualifier(sym) + else pkg.hasPackageFlag && sym.owner != pkg && requiresQualifier(sym) } def isNameInScope(name: Name) = lookupSymbol(name, _ => true).isSuccess diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 1bc5daac65..5062289ed1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -469,8 +469,7 @@ trait NamesDefaults { self: Analyzer => else { // isClass also works for methods in objects, owner is the ModuleClassSymbol if (param.owner.owner.isClass) { - // .toInterface: otherwise we get the method symbol of the impl class - param.owner.owner.toInterface.info.member(defGetterName) + param.owner.owner.info.member(defGetterName) } else { // the owner of the method is another method. find the default // getter in the context. diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index f6ee0c47a5..990edcd86d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -111,8 +111,6 @@ abstract class TreeCheckers extends Analyzer { newSyms += sym else if (prevTrees exists (t => (t eq tree) || (t.symbol == sym))) () - else if (prevTrees exists (_.symbol.owner == sym.owner.implClass)) - errorFn("Noticed " + ownerstr(sym) + " moving to implementation class.") else { val s1 = (prevTrees map wholetreestr).sorted.distinct val s2 = wholetreestr(tree) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index facb695447..16d3f5134b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3155,7 +3155,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (phase.erasedTypes) stats1 else { // As packages are open, it doesn't make sense to check double definitions here. Furthermore, - // it is expensive if the package is large. Instead, such double defininitions are checked in `Namers.enterInScope` + // it is expensive if the package is large. Instead, such double definitions are checked in `Namers.enterInScope` if (!context.owner.isPackageClass) checkNoDoubleDefs addSynthetics(stats1) @@ -4651,10 +4651,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper def findMixinSuper(site: Type): Type = { var ps = site.parents filter (_.typeSymbol.name == mix) if (ps.isEmpty) - ps = site.parents filter (_.typeSymbol.toInterface.name == mix) + ps = site.parents filter (_.typeSymbol.name == mix) if (ps.isEmpty) { debuglog("Fatal: couldn't find site " + site + " in " + site.parents.map(_.typeSymbol.name)) - if (phase.erasedTypes && context.enclClass.owner.isImplClass) { + if (phase.erasedTypes && context.enclClass.owner.isTrait) { // the reference to super class got lost during erasure restrictionError(tree.pos, unit, "traits may not select fields or methods from super[C] where C is a class") ErrorType diff --git a/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala b/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala index 4451651229..5d8831a607 100644 --- a/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala +++ b/src/compiler/scala/tools/nsc/util/ClassFileLookup.scala @@ -3,6 +3,8 @@ */ package scala.tools.nsc.util +import scala.tools.nsc.Settings +import scala.tools.nsc.classpath.{AggregateFlatClassPath, FlatClassPath, FlatClassPathFactory} import scala.tools.nsc.io.AbstractFile import java.net.URL @@ -39,6 +41,25 @@ trait ClassFileLookup[T] { def asSourcePathString: String } +object ClassFileLookup { + def createForFile(f: AbstractFile, current: ClassFileLookup[AbstractFile], settings: Settings): ClassFileLookup[AbstractFile] = current match { + case cp: ClassPath[_] => cp.context.newClassPath(f) + case _: FlatClassPath => FlatClassPathFactory.newClassPath(f, settings) + } + + def createAggregate(elems: Iterable[ClassFileLookup[AbstractFile]], current: ClassFileLookup[AbstractFile]): ClassFileLookup[AbstractFile] = { + assert(elems.nonEmpty) + if (elems.size == 1) elems.head + else current match { + case cp: ClassPath[_] => + new MergedClassPath(elems.asInstanceOf[Iterable[ClassPath[AbstractFile]]], cp.context) + + case _: FlatClassPath => + AggregateFlatClassPath.createAggregate(elems.asInstanceOf[Iterable[FlatClassPath]].toSeq : _*) + } + } +} + /** * Represents classes which can be loaded with a ClassfileLoader and/or SourcefileLoader. */ diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 2811520b67..6cdc3856cd 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -278,7 +278,7 @@ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[Ab f => // Optimization: We assume the file was not changed since `dir` called // `Path.apply` and categorized existent files as `Directory` - // or `File`. + // or `File` (avoids IO operation JFile.isDirectory()). val isDirectory = f match { case pf: io.PlainFile => pf.givenPath match { case _: io.Directory => true @@ -300,13 +300,6 @@ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[Ab override def toString() = "directory classpath: "+ origin.getOrElse("?") } -class DeltaClassPath[T](original: MergedClassPath[T], subst: Map[ClassPath[T], ClassPath[T]]) -extends MergedClassPath[T](original.entries map (e => subst getOrElse (e, e)), original.context) { - // not sure we should require that here. Commented out for now. - // require(subst.keySet subsetOf original.entries.toSet) - // We might add specialized operations for computing classes packages here. Not sure it's worth it. -} - /** * A classpath unifying multiple class- and sourcepath entries. */ diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 9cd2a2b8de..2f6d6511b2 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -65,6 +65,49 @@ import scala.io.StdIn * are provided for the "widening" of numeric values, for instance, converting a * Short value to a Long value as required, and to add additional higher-order * functions to Array values. These are described in more detail in the documentation of [[scala.Array]]. + * + * @groupname utilities Utility Methods + * @groupprio utilities 10 + * + * @groupname assertions Assertions + * @groupprio assertions 20 + * @groupdesc assertions These methods support program verfication and runtime correctness. + * + * @groupname console-output Console Output + * @groupprio console-output 30 + * @groupdesc console-output These methods provide output via the console. + * + * @groupname type-constraints Type Constraints + * @groupprio type-constraints 40 + * @groupdesc type-constraints These entities allows constraints between types to be stipulated. + * + * @groupname aliases Aliases + * @groupprio aliases 50 + * @groupdesc aliases These aliases bring selected immutable types into scope without any imports. + * + * @groupname conversions-string String Conversions + * @groupprio conversions-string 60 + * @groupdesc conversions-string Conversions to and from String and StringOps. + * + * @groupname implicit-classes-any Implicit Classes + * @groupprio implicit-classes-any 70 + * @groupdesc implicit-classes-any These implicit classes add useful extension methods to every type. + * + * @groupname implicit-classes-char CharSequence Conversions + * @groupprio implicit-classes-char 80 + * @groupdesc implicit-classes-char These implicit classes add CharSequence methods to Array[Char] and IndexedSeq[Char] instances. + * + * @groupname conversions-java-to-anyval Java to Scala + * @groupprio conversions-java-to-anyval 90 + * @groupdesc conversions-java-to-anyval Implicit conversion from Java primitive wrapper types to Scala equivalents. + * + * @groupname conversions-anyval-to-java Scala to Java + * @groupprio conversions-anyval-to-java 100 + * @groupdesc conversions-anyval-to-java Implicit conversion from Scala AnyVals to Java primitive wrapper types equivalents. + * + * @groupname conversions-array-to-wrapped-array Array to WrappedArray + * @groupprio conversions-array-to-wrapped-array 110 + * @groupdesc conversions-array-to-wrapped-array Conversions from Arrays to WrappedArrays. */ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** @@ -78,6 +121,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * val mapIntString = classOf[Map[Int,String]] * // mapIntString is java.lang.Class[Map[Int,String]] = interface scala.collection.immutable.Map * }}} + * @group utilities */ def classOf[T]: Class[T] = null // This is a stub method. The actual implementation is filled in by the compiler. @@ -85,19 +129,26 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * Java String (see the documentation corresponding to your Java version, for * example [[http://docs.oracle.com/javase/8/docs/api/java/lang/String.html]]) or * are added implicitly through [[scala.collection.immutable.StringOps]]. + * @group aliases */ type String = java.lang.String + /** @group aliases */ type Class[T] = java.lang.Class[T] // miscellaneous ----------------------------------------------------- scala.`package` // to force scala package object to be seen. scala.collection.immutable.List // to force Nil, :: to be seen. + /** @group aliases */ type Function[-A, +B] = Function1[A, B] + /** @group aliases */ type Map[A, +B] = immutable.Map[A, B] + /** @group aliases */ type Set[A] = immutable.Set[A] + /** @group aliases */ val Map = immutable.Map + /** @group aliases */ val Set = immutable.Set // Manifest types, companions, and incantations for summoning @@ -130,8 +181,11 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { def optManifest[T](implicit m: OptManifest[T]) = m // Minor variations on identity functions + /** @group utilities */ @inline def identity[A](x: A): A = x // @see `conforms` for the implicit version + /** @group utilities */ @inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` + /** @group utilities */ @inline def locally[T](x: T): T = x // to communicate intent and avoid unmoored statements // errors and asserts ------------------------------------------------- @@ -148,6 +202,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * * @see [[scala.annotation.elidable elidable]] * @param assertion the expression to test + * @group assertions */ @elidable(ASSERTION) def assert(assertion: Boolean) { @@ -162,6 +217,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * @see [[scala.annotation.elidable elidable]] * @param assertion the expression to test * @param message a String to include in the failure message + * @group assertions */ @elidable(ASSERTION) @inline final def assert(assertion: Boolean, message: => Any) { @@ -177,6 +233,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * * @see [[scala.annotation.elidable elidable]] * @param assumption the expression to test + * @group assertions */ @elidable(ASSERTION) def assume(assumption: Boolean) { @@ -193,6 +250,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * @see [[scala.annotation.elidable elidable]] * @param assumption the expression to test * @param message a String to include in the failure message + * @group assertions */ @elidable(ASSERTION) @inline final def assume(assumption: Boolean, message: => Any) { @@ -205,6 +263,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * for violating the condition. * * @param requirement the expression to test + * @group assertions */ def require(requirement: Boolean) { if (!requirement) @@ -217,6 +276,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * * @param requirement the expression to test * @param message a String to include in the failure message + * @group assertions */ @inline final def require(requirement: Boolean, message: => Any) { if (!requirement) @@ -225,6 +285,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** `???` can be used for marking methods that remain to be implemented. * @throws NotImplementedError + * @group utilities */ def ??? : Nothing = throw new NotImplementedError @@ -248,11 +309,13 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { // implicit classes ----------------------------------------------------- + /** @group implicit-classes-any */ implicit final class ArrowAssoc[A](private val self: A) extends AnyVal { @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y) def →[B](y: B): Tuple2[A, B] = ->(y) } + /** @group implicit-classes-any */ implicit final class Ensuring[A](private val self: A) extends AnyVal { def ensuring(cond: Boolean): A = { assert(cond); self } def ensuring(cond: Boolean, msg: => Any): A = { assert(cond, msg); self } @@ -260,6 +323,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { def ensuring(cond: A => Boolean, msg: => Any): A = { assert(cond(self), msg); self } } + /** @group implicit-classes-any */ implicit final class StringFormat[A](private val self: A) extends AnyVal { /** Returns string formatted according to given `format` string. * Format strings are as for `String.format` @@ -269,6 +333,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { } // SI-8229 retaining the pre 2.11 name for source compatibility in shadowing this implicit + /** @group implicit-classes-any */ implicit final class any2stringadd[A](private val self: A) extends AnyVal { def +(other: String): String = String.valueOf(self) + other } @@ -278,6 +343,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { @deprecated("Use Throwable#getStackTrace", "2.11.0") def getStackTraceString = self.getStackTrace().mkString("", EOL, EOL) } + /** @group implicit-classes-char */ implicit final class SeqCharSequence(val __sequenceOfChars: scala.collection.IndexedSeq[Char]) extends CharSequence { def length: Int = __sequenceOfChars.length def charAt(index: Int): Char = __sequenceOfChars(index) @@ -285,6 +351,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { override def toString = __sequenceOfChars mkString "" } + /** @group implicit-classes-char */ implicit final class ArrayCharSequence(val __arrayOfChars: Array[Char]) extends CharSequence { def length: Int = __arrayOfChars.length def charAt(index: Int): Char = __arrayOfChars(index) @@ -297,7 +364,9 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { def apply() = mutable.StringBuilder.newBuilder } + /** @group conversions-string */ @inline implicit def augmentString(x: String): StringOps = new StringOps(x) + /** @group conversions-string */ @inline implicit def unaugmentString(x: StringOps): String = x.repr // printing ----------------------------------------------------------- @@ -305,16 +374,19 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** Prints an object to `out` using its `toString` method. * * @param x the object to print; may be null. + * @group console-output */ def print(x: Any) = Console.print(x) /** Prints a newline character on the default output. + * @group console-output */ def println() = Console.println() /** Prints out an object to the default output, followed by a newline character. * * @param x the object to print. + * @group console-output */ def println(x: Any) = Console.println(x) @@ -332,6 +404,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments * * @see [[scala.StringContext.f StringContext.f]] + * @group console-output */ def printf(text: String, xs: Any*) = Console.print(text.format(xs: _*)) @@ -379,22 +452,38 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { // "Autoboxing" and "Autounboxing" --------------------------------------------------- + /** @group conversions-anyval-to-java */ implicit def byte2Byte(x: Byte): java.lang.Byte = x.asInstanceOf[java.lang.Byte] + /** @group conversions-anyval-to-java */ implicit def short2Short(x: Short): java.lang.Short = x.asInstanceOf[java.lang.Short] + /** @group conversions-anyval-to-java */ implicit def char2Character(x: Char): java.lang.Character = x.asInstanceOf[java.lang.Character] + /** @group conversions-anyval-to-java */ implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer] + /** @group conversions-anyval-to-java */ implicit def long2Long(x: Long): java.lang.Long = x.asInstanceOf[java.lang.Long] + /** @group conversions-anyval-to-java */ implicit def float2Float(x: Float): java.lang.Float = x.asInstanceOf[java.lang.Float] + /** @group conversions-anyval-to-java */ implicit def double2Double(x: Double): java.lang.Double = x.asInstanceOf[java.lang.Double] + /** @group conversions-anyval-to-java */ implicit def boolean2Boolean(x: Boolean): java.lang.Boolean = x.asInstanceOf[java.lang.Boolean] + /** @group conversions-java-to-anyval */ implicit def Byte2byte(x: java.lang.Byte): Byte = x.asInstanceOf[Byte] + /** @group conversions-java-to-anyval */ implicit def Short2short(x: java.lang.Short): Short = x.asInstanceOf[Short] + /** @group conversions-java-to-anyval */ implicit def Character2char(x: java.lang.Character): Char = x.asInstanceOf[Char] + /** @group conversions-java-to-anyval */ implicit def Integer2int(x: java.lang.Integer): Int = x.asInstanceOf[Int] + /** @group conversions-java-to-anyval */ implicit def Long2long(x: java.lang.Long): Long = x.asInstanceOf[Long] + /** @group conversions-java-to-anyval */ implicit def Float2float(x: java.lang.Float): Float = x.asInstanceOf[Float] + /** @group conversions-java-to-anyval */ implicit def Double2double(x: java.lang.Double): Double = x.asInstanceOf[Double] + /** @group conversions-java-to-anyval */ implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.asInstanceOf[Boolean] // Type Constraints -------------------------------------------------------------- @@ -415,6 +504,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * required lower bound. * * In part contributed by Jason Zaugg. + * @group type-constraints */ @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.") sealed abstract class <:<[-From, +To] extends (From => To) with Serializable @@ -422,6 +512,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { // The dollar prefix is to dodge accidental shadowing of this method // by a user-defined method of the same name (SI-7788). // The collections rely on this method. + /** @group type-constraints */ implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0") @@ -430,10 +521,12 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** An instance of `A =:= B` witnesses that the types `A` and `B` are equal. * * @see `<:<` for expressing subtyping constraints + * @group type-constraints */ @implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.") sealed abstract class =:=[From, To] extends (From => To) with Serializable private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x } + /** @group type-constraints */ object =:= { implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A] } @@ -513,6 +606,7 @@ private[scala] abstract class LowPriorityImplicits { @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) + /** @group conversions-array-to-wrapped-array */ implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = if (xs eq null) null else WrappedArray.make(xs) @@ -520,23 +614,35 @@ private[scala] abstract class LowPriorityImplicits { // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 // unique ones by way of this implicit, let's share one. + /** @group conversions-array-to-wrapped-array */ implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { if (xs eq null) null else if (xs.length == 0) WrappedArray.empty[T] else new WrappedArray.ofRef[T](xs) } + /** @group conversions-array-to-wrapped-array */ implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null + /** @group conversions-array-to-wrapped-array */ implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null + /** @group conversions-string */ implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null + /** @group conversions-string */ implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = diff --git a/src/library/scala/concurrent/SyncChannel.scala b/src/library/scala/concurrent/SyncChannel.scala index ec584b3eb0..735598935c 100644 --- a/src/library/scala/concurrent/SyncChannel.scala +++ b/src/library/scala/concurrent/SyncChannel.scala @@ -31,10 +31,10 @@ class SyncChannel[A] { pendingReads = pendingReads.tail // let reader continue - readReq set data + readReq put data // resolve write request - writeReq set true + writeReq put true } else { // enqueue write request @@ -57,10 +57,10 @@ class SyncChannel[A] { pendingWrites = pendingWrites.tail // let writer continue - writeReq set true + writeReq.put(true) // resolve read request - readReq set data + readReq.put (data) } else { // enqueue read request diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 178cd6d912..626540425f 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -304,7 +304,7 @@ private[concurrent] object Promise { /** Tries to add the callback, if already completed, it dispatches the callback to be executed. * Used by `onComplete()` to add callbacks to a promise and by `link()` to transfer callbacks - * to the root promise when linking two promises togehter. + * to the root promise when linking two promises together. */ @tailrec private def dispatchOrAddCallback(runnable: CallbackRunnable[T]): Unit = { diff --git a/src/library/scala/runtime/java8/JFunction1.java b/src/library/scala/runtime/java8/JFunction1.java index 7c3974e94a..2b8580271a 100644 --- a/src/library/scala/runtime/java8/JFunction1.java +++ b/src/library/scala/runtime/java8/JFunction1.java @@ -7,18 +7,6 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction1<T1, R> extends scala.Function1<T1, R> { - default void $init$() { - }; - - @Override - default <A> scala.Function1<T1, A> andThen(scala.Function1<R, A> g) { - return scala.Function1$class.andThen(this, g); - } - - @Override - default <A> scala.Function1<A, R> compose(scala.Function1<A, T1> g) { - return scala.Function1$class.compose(this, g); - } default void apply$mcVI$sp(int v1) { apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1)); } diff --git a/src/library/scala/runtime/java8/JFunction10.java b/src/library/scala/runtime/java8/JFunction10.java index f9af616641..9b9ab4a6c5 100644 --- a/src/library/scala/runtime/java8/JFunction10.java +++ b/src/library/scala/runtime/java8/JFunction10.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R> extends scala.Function10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, R>>>>>>>>>> curried() { - return scala.Function10$class.curried(this); - } - - default scala.Function1<scala.Tuple10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, R> tupled() { - return scala.Function10$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction11.java b/src/library/scala/runtime/java8/JFunction11.java index ba1235332b..b24c9a1ed0 100644 --- a/src/library/scala/runtime/java8/JFunction11.java +++ b/src/library/scala/runtime/java8/JFunction11.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R> extends scala.Function11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, R>>>>>>>>>>> curried() { - return scala.Function11$class.curried(this); - } - - default scala.Function1<scala.Tuple11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>, R> tupled() { - return scala.Function11$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction12.java b/src/library/scala/runtime/java8/JFunction12.java index 141388e768..09c90cb7e7 100644 --- a/src/library/scala/runtime/java8/JFunction12.java +++ b/src/library/scala/runtime/java8/JFunction12.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R> extends scala.Function12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, R>>>>>>>>>>>> curried() { - return scala.Function12$class.curried(this); - } - - default scala.Function1<scala.Tuple12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>, R> tupled() { - return scala.Function12$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction13.java b/src/library/scala/runtime/java8/JFunction13.java index 8d0be96a74..e8cc2b53e6 100644 --- a/src/library/scala/runtime/java8/JFunction13.java +++ b/src/library/scala/runtime/java8/JFunction13.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R> extends scala.Function13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, R>>>>>>>>>>>>> curried() { - return scala.Function13$class.curried(this); - } - - default scala.Function1<scala.Tuple13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>, R> tupled() { - return scala.Function13$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction14.java b/src/library/scala/runtime/java8/JFunction14.java index 58ab028716..327e442b4c 100644 --- a/src/library/scala/runtime/java8/JFunction14.java +++ b/src/library/scala/runtime/java8/JFunction14.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R> extends scala.Function14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, R>>>>>>>>>>>>>> curried() { - return scala.Function14$class.curried(this); - } - - default scala.Function1<scala.Tuple14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>, R> tupled() { - return scala.Function14$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction15.java b/src/library/scala/runtime/java8/JFunction15.java index 89a4a6cf61..bd2e3c00da 100644 --- a/src/library/scala/runtime/java8/JFunction15.java +++ b/src/library/scala/runtime/java8/JFunction15.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R> extends scala.Function15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, R>>>>>>>>>>>>>>> curried() { - return scala.Function15$class.curried(this); - } - - default scala.Function1<scala.Tuple15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>, R> tupled() { - return scala.Function15$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction16.java b/src/library/scala/runtime/java8/JFunction16.java index e3287b42ac..fb961e60ec 100644 --- a/src/library/scala/runtime/java8/JFunction16.java +++ b/src/library/scala/runtime/java8/JFunction16.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, R> extends scala.Function16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, R>>>>>>>>>>>>>>>> curried() { - return scala.Function16$class.curried(this); - } - - default scala.Function1<scala.Tuple16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>, R> tupled() { - return scala.Function16$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction17.java b/src/library/scala/runtime/java8/JFunction17.java index 508614e8b4..90a0b1d441 100644 --- a/src/library/scala/runtime/java8/JFunction17.java +++ b/src/library/scala/runtime/java8/JFunction17.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, R> extends scala.Function17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, scala.Function1<T17, R>>>>>>>>>>>>>>>>> curried() { - return scala.Function17$class.curried(this); - } - - default scala.Function1<scala.Tuple17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>, R> tupled() { - return scala.Function17$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction18.java b/src/library/scala/runtime/java8/JFunction18.java index 8aa9c5e2c3..cac24309e2 100644 --- a/src/library/scala/runtime/java8/JFunction18.java +++ b/src/library/scala/runtime/java8/JFunction18.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, R> extends scala.Function18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, scala.Function1<T17, scala.Function1<T18, R>>>>>>>>>>>>>>>>>> curried() { - return scala.Function18$class.curried(this); - } - - default scala.Function1<scala.Tuple18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>, R> tupled() { - return scala.Function18$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction19.java b/src/library/scala/runtime/java8/JFunction19.java index 89d739366e..bbfceac8c3 100644 --- a/src/library/scala/runtime/java8/JFunction19.java +++ b/src/library/scala/runtime/java8/JFunction19.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, R> extends scala.Function19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, scala.Function1<T17, scala.Function1<T18, scala.Function1<T19, R>>>>>>>>>>>>>>>>>>> curried() { - return scala.Function19$class.curried(this); - } - - default scala.Function1<scala.Tuple19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>, R> tupled() { - return scala.Function19$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction2.java b/src/library/scala/runtime/java8/JFunction2.java index 41f2adeae9..1e0293a7e8 100644 --- a/src/library/scala/runtime/java8/JFunction2.java +++ b/src/library/scala/runtime/java8/JFunction2.java @@ -7,17 +7,6 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction2<T1, T2, R> extends scala.Function2<T1, T2, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, R>> curried() { - return scala.Function2$class.curried(this); - } - - default scala.Function1<scala.Tuple2<T1, T2>, R> tupled() { - return scala.Function2$class.tupled(this); - } - default void apply$mcVII$sp(int v1, int v2) { apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2)); } diff --git a/src/library/scala/runtime/java8/JFunction20.java b/src/library/scala/runtime/java8/JFunction20.java index b8b4c11af7..543e657ea7 100644 --- a/src/library/scala/runtime/java8/JFunction20.java +++ b/src/library/scala/runtime/java8/JFunction20.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, R> extends scala.Function20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, scala.Function1<T17, scala.Function1<T18, scala.Function1<T19, scala.Function1<T20, R>>>>>>>>>>>>>>>>>>>> curried() { - return scala.Function20$class.curried(this); - } - - default scala.Function1<scala.Tuple20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>, R> tupled() { - return scala.Function20$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction21.java b/src/library/scala/runtime/java8/JFunction21.java index dbae0a0479..ecb0d8d287 100644 --- a/src/library/scala/runtime/java8/JFunction21.java +++ b/src/library/scala/runtime/java8/JFunction21.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, R> extends scala.Function21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, scala.Function1<T17, scala.Function1<T18, scala.Function1<T19, scala.Function1<T20, scala.Function1<T21, R>>>>>>>>>>>>>>>>>>>>> curried() { - return scala.Function21$class.curried(this); - } - - default scala.Function1<scala.Tuple21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>, R> tupled() { - return scala.Function21$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction22.java b/src/library/scala/runtime/java8/JFunction22.java index 2926ae336d..4945cd9db3 100644 --- a/src/library/scala/runtime/java8/JFunction22.java +++ b/src/library/scala/runtime/java8/JFunction22.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, R> extends scala.Function22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, scala.Function1<T10, scala.Function1<T11, scala.Function1<T12, scala.Function1<T13, scala.Function1<T14, scala.Function1<T15, scala.Function1<T16, scala.Function1<T17, scala.Function1<T18, scala.Function1<T19, scala.Function1<T20, scala.Function1<T21, scala.Function1<T22, R>>>>>>>>>>>>>>>>>>>>>> curried() { - return scala.Function22$class.curried(this); - } - - default scala.Function1<scala.Tuple22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>, R> tupled() { - return scala.Function22$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction3.java b/src/library/scala/runtime/java8/JFunction3.java index b75da0669b..ff657dbfd3 100644 --- a/src/library/scala/runtime/java8/JFunction3.java +++ b/src/library/scala/runtime/java8/JFunction3.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction3<T1, T2, T3, R> extends scala.Function3<T1, T2, T3, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, R>>> curried() { - return scala.Function3$class.curried(this); - } - - default scala.Function1<scala.Tuple3<T1, T2, T3>, R> tupled() { - return scala.Function3$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction4.java b/src/library/scala/runtime/java8/JFunction4.java index 20f89141bd..246c0d5c72 100644 --- a/src/library/scala/runtime/java8/JFunction4.java +++ b/src/library/scala/runtime/java8/JFunction4.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction4<T1, T2, T3, T4, R> extends scala.Function4<T1, T2, T3, T4, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, R>>>> curried() { - return scala.Function4$class.curried(this); - } - - default scala.Function1<scala.Tuple4<T1, T2, T3, T4>, R> tupled() { - return scala.Function4$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction5.java b/src/library/scala/runtime/java8/JFunction5.java index ce15f14e22..1d85c2989e 100644 --- a/src/library/scala/runtime/java8/JFunction5.java +++ b/src/library/scala/runtime/java8/JFunction5.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction5<T1, T2, T3, T4, T5, R> extends scala.Function5<T1, T2, T3, T4, T5, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, R>>>>> curried() { - return scala.Function5$class.curried(this); - } - - default scala.Function1<scala.Tuple5<T1, T2, T3, T4, T5>, R> tupled() { - return scala.Function5$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction6.java b/src/library/scala/runtime/java8/JFunction6.java index 07c0ca9665..0699c90830 100644 --- a/src/library/scala/runtime/java8/JFunction6.java +++ b/src/library/scala/runtime/java8/JFunction6.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction6<T1, T2, T3, T4, T5, T6, R> extends scala.Function6<T1, T2, T3, T4, T5, T6, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, R>>>>>> curried() { - return scala.Function6$class.curried(this); - } - - default scala.Function1<scala.Tuple6<T1, T2, T3, T4, T5, T6>, R> tupled() { - return scala.Function6$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction7.java b/src/library/scala/runtime/java8/JFunction7.java index f765ade092..57bc16a066 100644 --- a/src/library/scala/runtime/java8/JFunction7.java +++ b/src/library/scala/runtime/java8/JFunction7.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction7<T1, T2, T3, T4, T5, T6, T7, R> extends scala.Function7<T1, T2, T3, T4, T5, T6, T7, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, R>>>>>>> curried() { - return scala.Function7$class.curried(this); - } - - default scala.Function1<scala.Tuple7<T1, T2, T3, T4, T5, T6, T7>, R> tupled() { - return scala.Function7$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction8.java b/src/library/scala/runtime/java8/JFunction8.java index ffd362b0af..af22b888a3 100644 --- a/src/library/scala/runtime/java8/JFunction8.java +++ b/src/library/scala/runtime/java8/JFunction8.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction8<T1, T2, T3, T4, T5, T6, T7, T8, R> extends scala.Function8<T1, T2, T3, T4, T5, T6, T7, T8, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, R>>>>>>>> curried() { - return scala.Function8$class.curried(this); - } - - default scala.Function1<scala.Tuple8<T1, T2, T3, T4, T5, T6, T7, T8>, R> tupled() { - return scala.Function8$class.tupled(this); - } - - } diff --git a/src/library/scala/runtime/java8/JFunction9.java b/src/library/scala/runtime/java8/JFunction9.java index e3fca09be0..d3c6b26769 100644 --- a/src/library/scala/runtime/java8/JFunction9.java +++ b/src/library/scala/runtime/java8/JFunction9.java @@ -7,16 +7,4 @@ package scala.runtime.java8; @FunctionalInterface public interface JFunction9<T1, T2, T3, T4, T5, T6, T7, T8, T9, R> extends scala.Function9<T1, T2, T3, T4, T5, T6, T7, T8, T9, R> { - default void $init$() { - }; - - default scala.Function1<T1, scala.Function1<T2, scala.Function1<T3, scala.Function1<T4, scala.Function1<T5, scala.Function1<T6, scala.Function1<T7, scala.Function1<T8, scala.Function1<T9, R>>>>>>>>> curried() { - return scala.Function9$class.curried(this); - } - - default scala.Function1<scala.Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9>, R> tupled() { - return scala.Function9$class.tupled(this); - } - - } diff --git a/src/library/scala/sys/process/ProcessBuilderImpl.scala b/src/library/scala/sys/process/ProcessBuilderImpl.scala index 236baaf038..eef140c16a 100644 --- a/src/library/scala/sys/process/ProcessBuilderImpl.scala +++ b/src/library/scala/sys/process/ProcessBuilderImpl.scala @@ -56,7 +56,7 @@ private[process] trait ProcessBuilderImpl { success put false val t = Spawn({ runImpl(io) - success set true + success.put(true) }, io.daemonizeThreads) new ThreadProcess(t, success) diff --git a/src/library/scala/sys/process/ProcessImpl.scala b/src/library/scala/sys/process/ProcessImpl.scala index 559c0ee525..6da0dee056 100644 --- a/src/library/scala/sys/process/ProcessImpl.scala +++ b/src/library/scala/sys/process/ProcessImpl.scala @@ -30,8 +30,8 @@ private[process] trait ProcessImpl { def apply[T](f: => T): (Thread, () => T) = { val result = new SyncVar[Either[Throwable, T]] def run(): Unit = - try result set Right(f) - catch { case e: Exception => result set Left(e) } + try result.put(Right(f)) + catch { case e: Exception => result.put(Left(e)) } val t = Spawn(run()) @@ -91,8 +91,8 @@ private[process] trait ProcessImpl { protected lazy val (processThread, getExitValue, destroyer) = { val code = new SyncVar[Option[Int]]() - code set None - val thread = Spawn(code set runAndExitValue()) + code.put(None) + val thread = Spawn(code.put(runAndExitValue())) ( thread, diff --git a/src/partest-extras/scala/tools/partest/Util.scala b/src/partest-extras/scala/tools/partest/Util.scala index 60e9dbb0f9..511997ea35 100644 --- a/src/partest-extras/scala/tools/partest/Util.scala +++ b/src/partest-extras/scala/tools/partest/Util.scala @@ -14,7 +14,7 @@ object Util { * An alternative to [[scala.tools.partest.ReplTest]] that avoids the inconvenience of embedding * test code in a string. */ - def trace[A](a: A) = macro traceImpl[A] + def trace[A](a: A): A = macro traceImpl[A] import scala.reflect.macros.blackbox.Context def traceImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]): c.Expr[A] = { diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 44eee5cbfd..9ff4e89903 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -921,7 +921,6 @@ trait Definitions extends api.StandardDefinitions { def neverHasTypeParameters(sym: Symbol) = sym match { case _: RefinementClassSymbol => true case _: ModuleClassSymbol => true - case _: ImplClassSymbol => true case _ => ( sym.isPrimitiveValueClass diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index b022ba2981..35c927a5c3 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -157,7 +157,6 @@ class Flags extends ModifierFlags { final val MIXEDIN = 1L << 35 // term member has been mixed in final val EXISTENTIAL = 1L << 35 // type is an existential parameter or skolem final val EXPANDEDNAME = 1L << 36 // name has been expanded with class suffix - final val IMPLCLASS = 1L << 37 // symbol is an implementation class final val TRANS_FLAG = 1L << 38 // transient flag guaranteed to be reset after each phase. final val LOCKED = 1L << 39 // temporary flag to catch cyclic dependencies @@ -199,8 +198,7 @@ class Flags extends ModifierFlags { // 17: CONTRAVARIANT/M INCONSTRUCTOR LABEL // 25: DEFAULTPARAM/M TRAIT/M // 35: EXISTENTIAL MIXEDIN - // 37: IMPLCLASS PRESUPER/M - val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL | IMPLCLASS + val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL // ------- late flags (set by a transformer phase) --------------------------------- // @@ -210,7 +208,7 @@ class Flags extends ModifierFlags { // refchecks 7 [START] <latemethod> // specialize 13 [START] <latefinal> <notprivate> // explicitouter 14 [START] <notprotected> - // erasure 15 [START] <latedeferred> <lateinterface> + // erasure 15 [START] <latedeferred> // mixin 20 [START] <latemodule> <notoverride> // // lateMETHOD set in RefChecks#transformInfo. @@ -218,13 +216,11 @@ class Flags extends ModifierFlags { // notPRIVATE set in Symbols#makeNotPrivate, IExplicitOuter#transform, Inliners. // notPROTECTED set in ExplicitOuter#transform. // lateDEFERRED set in AddInterfaces, Mixin, etc. - // lateINTERFACE set in AddInterfaces#transformMixinInfo. // lateMODULE set in Mixin#transformInfo. // notOVERRIDE set in Mixin#preTransform. final val lateDEFERRED = (DEFERRED: Long) << LateShift final val lateFINAL = (FINAL: Long) << LateShift - final val lateINTERFACE = (INTERFACE: Long) << LateShift final val lateMETHOD = (METHOD: Long) << LateShift final val lateMODULE = (MODULE: Long) << LateShift @@ -439,7 +435,7 @@ class Flags extends ModifierFlags { case LIFTED => "<lifted>" // (1L << 34) case EXISTENTIAL => "<existential/mixedin>" // (1L << 35) case EXPANDEDNAME => "<expandedname>" // (1L << 36) - case IMPLCLASS => "<implclass/presuper>" // (1L << 37) + case PRESUPER => "<presuper>" // (1L << 37) case TRANS_FLAG => "<trans_flag>" // (1L << 38) case LOCKED => "<locked>" // (1L << 39) case SPECIALIZED => "<specialized>" // (1L << 40) @@ -456,7 +452,7 @@ class Flags extends ModifierFlags { case `lateDEFERRED` => "<latedeferred>" // (1L << 51) case `lateFINAL` => "<latefinal>" // (1L << 52) case `lateMETHOD` => "<latemethod>" // (1L << 53) - case `lateINTERFACE` => "<lateinterface>" // (1L << 54) + case 0x80000000000000L => "" // (1L << 54) case `lateMODULE` => "<latemodule>" // (1L << 55) case `notPROTECTED` => "<notprotected>" // (1L << 56) case `notOVERRIDE` => "<notoverride>" // (1L << 57) diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala index 5162b15206..673ea4fdef 100644 --- a/src/reflect/scala/reflect/internal/HasFlags.scala +++ b/src/reflect/scala/reflect/internal/HasFlags.scala @@ -120,6 +120,7 @@ trait HasFlags { def isSuperAccessor = hasFlag(SUPERACCESSOR) def isSynthetic = hasFlag(SYNTHETIC) def isTrait = hasFlag(TRAIT) && !hasFlag(PARAM) + def isTraitOrInterface = isTrait || isInterface def isDeferredOrJavaDefault = hasFlag(DEFERRED | JAVA_DEFAULTMETHOD) def isDeferredNotJavaDefault = isDeferred && !hasFlag(JAVA_DEFAULTMETHOD) diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index 15d68bcdfe..95b3b7fb14 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -254,7 +254,7 @@ trait Positions extends api.Positions { self: SymbolTable => case mdef: MemberDef => val annTrees = mdef.mods.annotations match { case Nil if mdef.symbol != null => - // After typechecking, annotations are mvoed from the modifiers + // After typechecking, annotations are moved from the modifiers // to the annotation on the symbol of the anotatee. mdef.symbol.annotations.map(_.original) case anns => anns diff --git a/src/reflect/scala/reflect/internal/Reporting.scala b/src/reflect/scala/reflect/internal/Reporting.scala index 2534f59c97..afdae81289 100644 --- a/src/reflect/scala/reflect/internal/Reporting.scala +++ b/src/reflect/scala/reflect/internal/Reporting.scala @@ -9,7 +9,7 @@ package internal /** Provides delegates to the reporter doing the actual work. * All forwarding methods should be marked final, - * but some subclasses out of our reach stil override them. + * but some subclasses out of our reach still override them. * * Eventually, this interface should be reduced to one method: `reporter`, * and clients should indirect themselves (reduce duplication of forwarders). diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 48e912d291..6abd7f2f19 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -104,7 +104,6 @@ trait StdNames { val ANON_FUN_NAME: NameType = "$anonfun" val EMPTY: NameType = "" val EMPTY_PACKAGE_NAME: NameType = "<empty>" - val IMPL_CLASS_SUFFIX = "$class" val IMPORT: NameType = "<import>" val MODULE_SUFFIX_NAME: NameType = MODULE_SUFFIX_STRING val MODULE_VAR_SUFFIX: NameType = "$module" @@ -303,8 +302,6 @@ trait StdNames { def dropSingletonName(name: Name): TypeName = (name dropRight SINGLETON_SUFFIX.length).toTypeName def singletonName(name: Name): TypeName = (name append SINGLETON_SUFFIX).toTypeName - def implClassName(name: Name): TypeName = (name append IMPL_CLASS_SUFFIX).toTypeName - def interfaceName(implname: Name): TypeName = (implname dropRight IMPL_CLASS_SUFFIX.length).toTypeName } abstract class TermNames extends Keywords with TermNamesApi { @@ -378,7 +375,6 @@ trait StdNames { def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX - def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 9a3f6a6f3f..34f9417e57 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -478,10 +478,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newAnonymousFunctionValue(pos: Position, newFlags: Long = 0L): TermSymbol = 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 */ @@ -588,7 +584,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isAnonymousClass = false def isCaseClass = false def isConcreteClass = false - def isImplClass = false // the implementation class of a trait + @deprecated("Trait implementation classes have been removed in Scala 2.12", "2.12.0") + def isImplClass = false def isJavaInterface = false def isNumericValueClass = false def isPrimitiveValueClass = false @@ -838,7 +835,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** The package object symbol corresponding to this package or package class symbol, or NoSymbol otherwise */ def packageObject: Symbol = if (isPackageClass) tpe.packageObject - else if (isPackage) moduleClass.packageObject + else if (hasPackageFlag) moduleClass.packageObject else NoSymbol /** If this is a constructor, its owner: otherwise this. @@ -936,21 +933,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isCaseCopy = isMethod && owner.isCase && isSynthetic && name == nme.copy - /** Is this symbol a trait which needs an implementation class? */ - 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 = isPrivate || ( - (owner.isTrait || owner.isImplClass) && ( - hasAllFlags(LIFTED | MODULE | METHOD) - || isConstructor - || hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE) - ) - ) final def isModuleVar = hasFlag(MODULEVAR) /** @@ -987,7 +969,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Is this symbol a static member of its class? (i.e. needs to be implemented as a Java static?) */ final def isStaticMember: Boolean = - hasFlag(STATIC) || owner.isImplClass + hasFlag(STATIC) /** Does this symbol denote a class that defines static symbols? */ final def isStaticOwner: Boolean = @@ -1261,7 +1243,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def needsModuleSuffix = ( hasModuleFlag && !isMethod - && !isImplClass && !isJavaDefined ) /** These should be moved somewhere like JavaPlatform. @@ -1334,9 +1315,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol = new MethodSymbol(this, pos, name) initFlags newFlags @@ -1375,8 +1353,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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) } @@ -2085,12 +2061,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def sourceModule: Symbol = 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 - * appended to it. - */ - final def implClass: Symbol = owner.info.decl(tpnme.implClassName(name)) - /** The class that is logically an outer class of given `clazz`. * This is the enclosing class, except for classes defined locally to constructors, * where it is the outer class of the enclosing class. @@ -2294,16 +2264,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => owner.rawInfo } - /** If this symbol is an implementation class, its interface, otherwise the symbol itself - * The method follows two strategies to determine the interface. - * - during or after erasure, it takes the last parent of the implementation class - * (which is always the interface, by convention) - * - before erasure, it looks up the interface name in the scope of the owner of the class. - * This only works for implementation classes owned by other classes or traits. - * !!! Why? - */ - def toInterface: Symbol = this - /** The module class corresponding to this module. */ def moduleClass: Symbol = NoSymbol @@ -2423,8 +2383,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => var bcs = base.info.baseClasses dropWhile (owner != _) drop 1 var sym: Symbol = NoSymbol while (!bcs.isEmpty && sym == NoSymbol) { - if (!bcs.head.isImplClass) - sym = matchingSymbol(bcs.head, base.thisType).suchThat(!_.isDeferred) + sym = matchingSymbol(bcs.head, base.thisType).suchThat(!_.isDeferred) bcs = bcs.tail } sym @@ -2558,7 +2517,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** String representation of symbol's definition key word */ final def keyString: String = if (isJavaInterface) "interface" - else if (isTrait && !isImplClass) "trait" + else if (isTrait) "trait" else if (isClass) "class" else if (isType && !isParameter) "type" else if (isVariable) "var" @@ -2585,7 +2544,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isSetter) ("setter", if (isSourceMethod) "method" else "value", "SET") else if (isTerm && isLazy) ("lazy value", "lazy value", "LAZ") else if (isVariable) ("field", "variable", "VAR") - else if (isImplClass) ("implementation class", "class", "IMPL") else if (isTrait) ("trait", "trait", "TRT") else if (isClass) ("class", "class", "CLS") else if (isType) ("type", "type", "TPE") @@ -3223,7 +3181,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def resolveOverloadedFlag(flag: Long) = flag match { case INCONSTRUCTOR => "<inconstructor>" // INCONSTRUCTOR / CONTRAVARIANT / LABEL case EXISTENTIAL => "<existential>" // EXISTENTIAL / MIXEDIN - case IMPLCLASS => "<implclass>" // IMPLCLASS / PRESUPER case _ => super.resolveOverloadedFlag(flag) } @@ -3235,7 +3192,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 @@ -3253,13 +3209,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => // 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(tpnme.interfaceName(name)) - } - else super.toInterface - ) /** Is this class locally defined? * A class is local, if @@ -3290,7 +3239,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound)) - def primaryConstructorName = if (this hasFlag TRAIT | IMPLCLASS) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR + def primaryConstructorName = if (this hasFlag TRAIT) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR override def primaryConstructor = { val c = info decl primaryConstructorName @@ -3436,12 +3385,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } - 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) { override def sourceModule = companionModule diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index b43ea640d9..cba34aa220 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1161,6 +1161,10 @@ trait Trees extends api.Trees { def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix) + /** Selection of a method in an arbitrary ancestor */ + def SuperSelect(clazz: Symbol, sym: Symbol): Tree = + Select(Super(clazz, tpnme.EMPTY), sym) + def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 24709cf379..f385ca08c9 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1196,7 +1196,6 @@ trait Types object ThisType extends ThisTypeExtractor { def apply(sym: Symbol): Type = ( if (!phase.erasedTypes) unique(new UniqueThisType(sym)) - else if (sym.isImplClass) sym.typeOfThis else sym.tpe_* ) } diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index fffe4dd881..412b14d329 100644 --- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -223,7 +223,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D def +=(elem: A) = this + elem - // from scala.reflect.interanl.Set + // from scala.reflect.internal.Set override def addEntry(x: A) { this += x } // remove an element from this set and return this set diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 40f2a1ef90..49799136de 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -999,9 +999,9 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive } val cls = - if (jclazz.isMemberClass && !nme.isImplClassName(jname)) + if (jclazz.isMemberClass) lookupClass - else if (jclazz.isLocalClass0 || scalacShouldntLoadClass(jname)) + else if (jclazz.isLocalClass0) // local classes and implementation classes not preserved by unpickling - treat as Java // // upd. but only if they cannot be loaded as top-level classes diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index d92e37953f..dd15a09b7e 100644 --- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -80,12 +80,6 @@ object ReflectionUtils { accessor invoke outer } - def isTraitImplementation(fileName: String) = fileName endsWith "$class.class" - - def scalacShouldntLoadClassfile(fileName: String) = isTraitImplementation(fileName) - - def scalacShouldntLoadClass(name: scala.reflect.internal.SymbolTable#Name) = scalacShouldntLoadClassfile(name + ".class") - object PrimitiveOrArray { def unapply(jclazz: jClass[_]) = jclazz.isPrimitive || jclazz.isArray } diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index 43ab41f541..768a3d5ce5 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -3,7 +3,6 @@ package reflect package runtime import scala.collection.mutable -import scala.reflect.runtime.ReflectionUtils.scalacShouldntLoadClass import scala.reflect.internal.Flags._ private[reflect] trait SymbolLoaders { self: SymbolTable => @@ -125,7 +124,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => val e = super.lookupEntry(name) if (e != null) e - else if (scalacShouldntLoadClass(name) || (negatives contains name)) + else if (negatives contains name) null else { val path = diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 4f0c0253e9..313ec89311 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -176,9 +176,6 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb 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 diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 459450a94e..56d62f3efc 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -633,10 +633,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } def alreadyDefined(clsName: String) = intp.classLoader.tryToLoadClass(clsName).isDefined - val exists = entries.filter(_.hasExtension("class")).map(classNameOf).exists(alreadyDefined) + val existingClass = entries.filter(_.hasExtension("class")).map(classNameOf).find(alreadyDefined) if (!f.exists) echo(s"The path '$f' doesn't seem to exist.") - else if (exists) echo(s"The path '$f' cannot be loaded, because existing classpath entries conflict.") // TODO tell me which one + else if (existingClass.nonEmpty) echo(s"The path '$f' cannot be loaded, it contains a classfile that already exists on the classpath: ${existingClass.get}") else { addedClasspath = ClassPath.join(addedClasspath, f.path) intp.addUrlsToClassPath(f.toURI.toURL) diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala index 3a2177a4cb..e3dc72b717 100644 --- a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala +++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala @@ -5,12 +5,14 @@ package scala.tools.nsc.interpreter import scala.reflect.internal.util.RangePosition +import scala.reflect.io.AbstractFile import scala.tools.nsc.backend.JavaPlatform +import scala.tools.nsc.settings.ClassPathRepresentationType +import scala.tools.nsc.util.ClassPath.DefaultJavaContext +import scala.tools.nsc.util.{ClassPath, MergedClassPath, DirectoryClassPath} import scala.tools.nsc.{interactive, Settings} -import scala.tools.nsc.io._ import scala.tools.nsc.reporters.StoreReporter -import scala.tools.nsc.util.ClassPath.DefaultJavaContext -import scala.tools.nsc.util.{DirectoryClassPath, MergedClassPath} +import scala.tools.nsc.classpath._ trait PresentationCompilation { self: IMain => @@ -55,8 +57,14 @@ trait PresentationCompilation { * You may downcast the `reporter` to `StoreReporter` to access type errors. */ def newPresentationCompiler(): interactive.Global = { - val replOutClasspath: DirectoryClassPath = new DirectoryClassPath(replOutput.dir, DefaultJavaContext) - val mergedClasspath = new MergedClassPath[AbstractFile](replOutClasspath :: global.platform.classPath :: Nil, DefaultJavaContext) + def mergedFlatClasspath = { + val replOutClasspath = FlatClassPathFactory.newClassPath(replOutput.dir, settings) + AggregateFlatClassPath(replOutClasspath :: global.platform.flatClassPath :: Nil) + } + def mergedRecursiveClasspath = { + val replOutClasspath: DirectoryClassPath = new DirectoryClassPath(replOutput.dir, DefaultJavaContext) + new MergedClassPath[AbstractFile](replOutClasspath :: global.platform.classPath :: Nil, DefaultJavaContext) + } def copySettings: Settings = { val s = new Settings(_ => () /* ignores "bad option -nc" errors, etc */) s.processArguments(global.settings.recreateArgs, processAll = false) @@ -65,10 +73,18 @@ trait PresentationCompilation { } val storeReporter: StoreReporter = new StoreReporter val interactiveGlobal = new interactive.Global(copySettings, storeReporter) { self => - override lazy val platform: ThisPlatform = new JavaPlatform { - val global: self.type = self - - override def classPath: PlatformClassPath = mergedClasspath + override lazy val platform: ThisPlatform = { + if (settings.YclasspathImpl.value == ClassPathRepresentationType.Flat) { + new JavaPlatform { + val global: self.type = self + override private[nsc] lazy val flatClassPath: FlatClassPath = mergedFlatClasspath + } + } else { + new JavaPlatform { + val global: self.type = self + override def classPath: ClassPath[AbstractFile] = mergedRecursiveClasspath + } + } } } new interactiveGlobal.TyperRun() @@ -78,7 +94,7 @@ trait PresentationCompilation { abstract class PresentationCompileResult { val compiler: scala.tools.nsc.interactive.Global def unit: compiler.RichCompilationUnit - /** The length of synthetic code the precedes the user writtn code */ + /** The length of synthetic code the precedes the user written code */ def preambleLength: Int def cleanup(): Unit = { compiler.askShutdown() diff --git a/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala b/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala index eeb861e246..5d0b6782bc 100644 --- a/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/comment/Comment.scala @@ -63,7 +63,7 @@ abstract class Comment { /** A list of other resources to see, including links to other entities or * to external documentation. The empty list is used when no other resource - * is mentionned. */ + * is mentioned. */ def see: List[Body] /** A description of the result of the entity. Typically, this provides additional diff --git a/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala index 524f94443d..757f13f79a 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala @@ -455,7 +455,7 @@ trait ValueParam extends ParameterEntity { /** The type of this value parameter. */ def resultType: TypeEntity - /** The devault value of this value parameter, if it has been defined. */ + /** The default value of this value parameter, if it has been defined. */ def defaultValue: Option[TreeEntity] /** Whether this value parameter is implicit. */ diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala index bccb65aa5f..928cb34d30 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala @@ -51,7 +51,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { lazy val dotRunner = new DotRunner(settings) } _modelFinished = true - // complete the links between model entities, everthing that couldn't have been done before + // complete the links between model entities, everything that couldn't have been done before universe.rootPackage.completeModel() Some(universe) filter (_.rootPackage != null) diff --git a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala index 3b7eb4e947..464cacc99a 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala @@ -163,7 +163,7 @@ trait DiagramDirectiveParser { case Nil => defaultFilter - // compute the exact filters. By including the annotation, the diagram is autmatically added + // compute the exact filters. By including the annotation, the diagram is automatically added case _ => tFilter -= System.currentTimeMillis var hideDiagram0: Boolean = false diff --git a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala index 86900f26c9..bbcb18353a 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala @@ -63,7 +63,7 @@ trait DiagramFactory extends DiagramDirectiveParser { case d: TemplateImpl if !classExcluded(d) => NormalNode(makeType(d.sym.tpe, tpl), Some(d))() }.sortBy(_.tpl.get.name)(implicitly[Ordering[String]].reverse) - // outgoing implicit coversions + // outgoing implicit conversions lazy val outgoingImplicitNodes = tpl.outgoingImplicitlyConvertedClasses.map { case (outgoingTpl, outgoingType, conv) => ImplicitNode(outgoingType, Some(outgoingTpl))(implicitTooltip(from=tpl, to=tpl, conv=conv)) |