Skip to content
10 changes: 5 additions & 5 deletions src/compiler/scala/reflect/quasiquotes/Reifiers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ trait Reifiers { self: Quasiquotes =>
* and ends with reified tree:
*
* {
* val name$1: universe.TermName = universe.build.freshTermName(prefix1)
* val name\$1: universe.TermName = universe.build.freshTermName(prefix1)
* ...
* val name$N: universe.TermName = universe.build.freshTermName(prefixN)
* val name\$N: universe.TermName = universe.build.freshTermName(prefixN)
* tree
* }
*
Expand Down Expand Up @@ -348,9 +348,9 @@ trait Reifiers { self: Quasiquotes =>
*
* Sample execution of previous concrete list reifier:
*
* > val lst = List(foo, bar, qq$f3948f9s$1)
* > val lst = List(foo, bar, qq\$f3948f9s\$1)
* > reifyHighRankList(lst) { ... } { ... }
* q"List($foo, $bar) ++ ${holeMap(qq$f3948f9s$1).tree}"
* q"List(\$foo, \$bar) ++ \${holeMap(qq\$f3948f9s\$1).tree}"
*/
def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree

Expand All @@ -373,7 +373,7 @@ trait Reifiers { self: Quasiquotes =>
case List(Placeholder(Hole(tree, DotDotDot))) => tree
}

/** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put
/** Reifies arbitrary list filling ..\$x and ...\$y holeMap when they are put
* in the correct position. Falls back to regular reification for zero rank
* elements.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/ScriptRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import util.Exceptional.unwrap
* For example, here is a complete Scala script on Unix:
* {{{
* #!/bin/sh
* exec scala "$0" "$@"
* exec scala "\$0" "\$@"
* !#
* Console.println("Hello, world!")
* args.toList foreach Console.println
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/ast/TreeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
*
* x.asInstanceOf[`pt`] up to phase uncurry
* x.asInstanceOf[`pt`]() if after uncurry but before erasure
* x.$asInstanceOf[`pt`]() if at or after erasure
* x.\$asInstanceOf[`pt`]() if at or after erasure
*/
override def mkCast(tree: Tree, pt: Type): Tree = {
debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
asm.Opcodes.PUTSTATIC,
thisBType.internalName,
strMODULE_INSTANCE_FIELD,
thisBType.descriptor
thisBTypeDescriptor
)
}
}
Expand Down Expand Up @@ -1092,7 +1092,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
if (style == Super) {
if (receiverClass.isTrait && !method.isJavaDefined) {
val staticDesc = MethodBType(typeToBType(method.owner.info) :: bmType.argumentTypes, bmType.returnType).descriptor
val staticName = traitSuperAccessorName(method).toString
val staticName = traitSuperAccessorName(method)
bc.invokestatic(receiverName, staticName, staticDesc, isInterface, pos)
} else {
if (receiverClass.isTraitOrInterface) {
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ abstract class BCodeHelpers extends BCodeIdiomatic {

def needsStaticImplMethod(sym: Symbol) = sym.hasAttachment[global.mixer.NeedStaticImpl.type]

final def traitSuperAccessorName(sym: Symbol): Name = {
final def traitSuperAccessorName(sym: Symbol): String = {
val name = sym.javaSimpleName
if (sym.isMixinConstructor) name
else name.append(nme.NAME_JOIN_STRING)
if (sym.isMixinConstructor) name.toString
else name + nme.NAME_JOIN_STRING
}

/**
Expand Down
22 changes: 12 additions & 10 deletions src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
final val MaximumJvmParameters = 254

// current class
var cnode: asm.tree.ClassNode = null
var thisBType: ClassBType = null
var cnode: asm.tree.ClassNode = null
var thisBType: ClassBType = null
var thisBTypeDescriptor: String = null

var claszSymbol: Symbol = null
var isCZParcelable = false
Expand All @@ -89,11 +90,12 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
def genPlainClass(cd: ClassDef) {
assert(cnode == null, "GenBCode detected nested methods.")

claszSymbol = cd.symbol
isCZParcelable = isAndroidParcelableClass(claszSymbol)
isCZStaticModule = isStaticModuleClass(claszSymbol)
isCZRemote = isRemote(claszSymbol)
thisBType = classBTypeFromSymbol(claszSymbol)
claszSymbol = cd.symbol
isCZParcelable = isAndroidParcelableClass(claszSymbol)
isCZStaticModule = isStaticModuleClass(claszSymbol)
isCZRemote = isRemote(claszSymbol)
thisBType = classBTypeFromSymbol(claszSymbol)
thisBTypeDescriptor = thisBType.descriptor

cnode = new ClassNode1()

Expand Down Expand Up @@ -194,7 +196,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
val fv =
cnode.visitField(mods,
strMODULE_INSTANCE_FIELD,
thisBType.descriptor,
thisBTypeDescriptor,
null, // no java-generic-signature
null // no initial value
)
Expand Down Expand Up @@ -498,7 +500,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
genDefDef(statified)
} else {
val forwarderDefDef = {
val dd1 = global.gen.mkStatic(deriveDefDef(dd)(_ => EmptyTree), traitSuperAccessorName(sym), _.cloneSymbol.withoutAnnotations)
val dd1 = global.gen.mkStatic(deriveDefDef(dd)(_ => EmptyTree), newTermName(traitSuperAccessorName(sym)), _.cloneSymbol.withoutAnnotations)
dd1.symbol.setFlag(Flags.ARTIFACT).resetFlag(Flags.OVERRIDE)
val selfParam :: realParams = dd1.vparamss.head.map(_.symbol)
deriveDefDef(dd1)(_ =>
Expand Down Expand Up @@ -622,7 +624,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
if (!hasStaticBitSet) {
mnode.visitLocalVariable(
"this",
thisBType.descriptor,
thisBTypeDescriptor,
null,
veryFirstProgramPoint,
onePastLastProgramPoint,
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1098,10 +1098,10 @@ object BTypes {
* @param isEffectivelyFinal True if the class cannot have subclasses: final classes, module
* classes.
*
* @param sam If this class is a SAM type, the SAM's "$name$descriptor".
* @param sam If this class is a SAM type, the SAM's "\$name\$descriptor".
*
* @param methodInfos The [[MethodInlineInfo]]s for the methods declared in this class.
* The map is indexed by the string s"$name$descriptor" (to
* The map is indexed by the string s"\$name\$descriptor" (to
* disambiguate overloads).
*
* @param warning Contains an warning message if an error occurred when building this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ abstract class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass))

if (needsStaticImplMethod(methodSym)) {
val staticName = traitSuperAccessorName(methodSym).toString
val staticName = traitSuperAccessorName(methodSym)
val selfParam = methodSym.newSyntheticValueParam(methodSym.owner.typeConstructor, nme.SELF)
val staticMethodType = methodSym.info match {
case mt@MethodType(params, res) => copyMethodType(mt, selfParam :: params, res)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

package scala.tools.nsc.backend.jvm

import java.io.{BufferedOutputStream, DataOutputStream, FileOutputStream, IOException}
import java.io.{DataOutputStream, IOException}
import java.nio.ByteBuffer
import java.nio.channels.{ClosedByInterruptException, FileChannel}
import java.nio.charset.StandardCharsets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ package scala.tools.nsc.backend.jvm
* val m = cn.methods.iterator.asScala.find(_.name == "f").head
*
* // the value is read from the classfile, so it's 4
* println(s"maxLocals: ${m.maxLocals}, maxStack: ${m.maxStack}") // maxLocals: 5, maxStack: 4
* println(s"maxLocals: \${m.maxLocals}, maxStack: \${m.maxStack}") // maxLocals: 5, maxStack: 4
*
* // we can safely set it to 2 for running the analyzer.
* m.maxStack = 2
Expand Down
18 changes: 9 additions & 9 deletions src/compiler/scala/tools/nsc/backend/jvm/opt/BoxUnbox.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ abstract class BoxUnbox {
* f(1, 2) // invokes the generic `apply`
* }
*
* The closure optimizer re-writes the `apply` call to `anonfun$adapted` method, which takes
* The closure optimizer re-writes the `apply` call to `anonfun\$adapted` method, which takes
* boxed arguments. After inlining this method, we get
*
* def t2 = {
* val a = boxByte(1)
* val b = boxInteger(2)
* val r = boxInteger(anonfun$(unboxByte(a), unboxInt(b)))
* val r = boxInteger(anonfun\$(unboxByte(a), unboxInt(b)))
* unboxInt(r)
* }
*
Expand Down Expand Up @@ -166,8 +166,8 @@ abstract class BoxUnbox {
*
*
* Special case for tuples wrt specialization: a tuple getter may box or unbox the value stored
* in the tuple: calling `_1` on a `Tuple2$mcII$sp` boxes the primitive Int stored in the tuple.
* Similarly, calling `_1$mcI$sp` on a non-specialized `Tuple2` unboxes the Integer in the tuple.
* in the tuple: calling `_1` on a `Tuple2\$mcII\$sp` boxes the primitive Int stored in the tuple.
* Similarly, calling `_1\$mcI\$sp` on a non-specialized `Tuple2` unboxes the Integer in the tuple.
* When eliminating such getters, we have to introduce appropriate box / unbox calls.
*
*
Expand Down Expand Up @@ -629,7 +629,7 @@ abstract class BoxUnbox {

/**
* If `mi` is an invocation of a method on Predef, check if the receiver is a GETSTATIC of
* Predef.MODULE$ and return it.
* Predef.MODULE\$ and return it.
*/
def checkReceiverPredefLoad(mi: MethodInsnNode, prodCons: ProdConsAnalyzer): Option[AbstractInsnNode] = {
val numArgs = Type.getArgumentTypes(mi.desc).length
Expand Down Expand Up @@ -913,7 +913,7 @@ abstract class BoxUnbox {

/**
* If this box consumer extracts a boxed value and applies a conversion, this method returns
* equivalent conversion operations. For example, invoking `_1$mcI$sp` on a non-specialized
* equivalent conversion operations. For example, invoking `_1\$mcI\$sp` on a non-specialized
* `Tuple2` extracts the Integer value and unboxes it.
*/
def postExtractionAdaptationOps(typeOfExtractedValue: Type): List[AbstractInsnNode] = this match {
Expand All @@ -929,15 +929,15 @@ abstract class BoxUnbox {

/** Static extractor (BoxesRunTime.unboxToInt) or GETFIELD or getter invocation */
case class StaticGetterOrInstanceRead(consumer: AbstractInsnNode) extends BoxConsumer
/** A getter that boxes the returned value, e.g., `Tuple2$mcII$sp._1` */
/** A getter that boxes the returned value, e.g., `Tuple2\$mcII\$sp._1` */
case class PrimitiveBoxingGetter(consumer: MethodInsnNode) extends BoxConsumer
/** A getter that unboxes the returned value, e.g., `Tuple2._1$mcI$sp` */
/** A getter that unboxes the returned value, e.g., `Tuple2._1\$mcI\$sp` */
case class PrimitiveUnboxingGetter(consumer: MethodInsnNode, unboxedPrimitive: Type) extends BoxConsumer
/** An extractor method in a Scala module, e.g., `Predef.Integer2int` */
case class ModuleGetter(moduleLoad: AbstractInsnNode, consumer: MethodInsnNode) extends BoxConsumer
/** PUTFIELD or setter invocation */
case class StaticSetterOrInstanceWrite(consumer: AbstractInsnNode) extends BoxConsumer
/** `.$isInstanceOf[T]` (can be statically proven true or false) */
/** `.\$isInstanceOf[T]` (can be statically proven true or false) */
case class BoxedPrimitiveTypeCheck(consumer: AbstractInsnNode, success: Boolean) extends BoxConsumer
/** An unknown box consumer */
case class EscapingConsumer(consumer: AbstractInsnNode) extends BoxConsumer
Expand Down
53 changes: 32 additions & 21 deletions src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
package scala.tools.nsc.classpath

import java.net.URL

import scala.collection.mutable.ArrayBuffer
import scala.reflect.internal.FatalError
import scala.reflect.io.AbstractFile
import scala.tools.nsc.util.ClassPath
import scala.tools.nsc.util.ClassRepresentation
import scala.tools.nsc.util.{ClassPath, ClassRepresentation, EfficientClassPath}

/**
* A classpath unifying multiple class- and sourcepath entries.
Expand All @@ -30,21 +30,21 @@ import scala.tools.nsc.util.ClassRepresentation
case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
override def findClassFile(className: String): Option[AbstractFile] = {
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)
aggregatesForPackage(pkg).iterator.map(_.findClassFile(className)).collectFirst {
aggregatesForPackage(PackageName(pkg)).iterator.map(_.findClassFile(className)).collectFirst {
case Some(x) => x
}
}
private[this] val packageIndex: collection.mutable.Map[String, Seq[ClassPath]] = collection.mutable.Map()
private def aggregatesForPackage(pkg: String): Seq[ClassPath] = packageIndex.synchronized {
packageIndex.getOrElseUpdate(pkg, aggregates.filter(_.hasPackage(pkg)))
private def aggregatesForPackage(pkg: PackageName): Seq[ClassPath] = packageIndex.synchronized {
packageIndex.getOrElseUpdate(pkg.dottedString, aggregates.filter(_.hasPackage(pkg)))
}

// This method is performance sensitive as it is used by SBT's ExtractDependencies phase.
override def findClass(className: String): Option[ClassRepresentation] = {
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)

def findEntry(isSource: Boolean): Option[ClassRepresentation] = {
aggregatesForPackage(pkg).iterator.map(_.findClass(className)).collectFirst {
aggregatesForPackage(PackageName(pkg)).iterator.map(_.findClass(className)).collectFirst {
case Some(s: SourceFileEntry) if isSource => s
case Some(s: ClassFileEntry) if !isSource => s
}
Expand All @@ -66,31 +66,44 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {

override def asSourcePathString: String = ClassPath.join(aggregates map (_.asSourcePathString): _*)

override private[nsc] def packages(inPackage: String): Seq[PackageEntry] = {
override private[nsc] def packages(inPackage: PackageName): Seq[PackageEntry] = {
val aggregatedPackages = aggregates.flatMap(_.packages(inPackage)).distinct
aggregatedPackages
}

override private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] =
override private[nsc] def classes(inPackage: PackageName): Seq[ClassFileEntry] =
getDistinctEntries(_.classes(inPackage))

override private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] =
override private[nsc] def sources(inPackage: PackageName): Seq[SourceFileEntry] =
getDistinctEntries(_.sources(inPackage))

override private[nsc] def hasPackage(pkg: String) = aggregates.exists(_.hasPackage(pkg))
override private[nsc] def list(inPackage: String): ClassPathEntries = {
val (packages, classesAndSources) = aggregates.map { cp =>
override private[nsc] def hasPackage(pkg: PackageName) = aggregates.exists(_.hasPackage(pkg))
override private[nsc] def list(inPackage: PackageName): ClassPathEntries = {
val packages: java.util.HashSet[PackageEntry] = new java.util.HashSet[PackageEntry]()
val classesAndSourcesBuffer = collection.mutable.ArrayBuffer[ClassRepresentation]()
val onPackage: PackageEntry => Unit = packages.add(_)
val onClassesAndSources: ClassRepresentation => Unit = classesAndSourcesBuffer += _

aggregates.foreach { cp =>
try {
cp.list(inPackage)
cp match {
case ecp: EfficientClassPath =>
ecp.list(inPackage, onPackage, onClassesAndSources)
case _ =>
val entries = cp.list(inPackage)
entries._1.foreach(entry => packages.add(entry))
classesAndSourcesBuffer ++= entries._2
}
} catch {
case ex: java.io.IOException =>
val e = FatalError(ex.getMessage)
e.initCause(ex)
throw e
}
}.unzip
val distinctPackages = packages.flatten.distinct
val distinctClassesAndSources = mergeClassesAndSources(classesAndSources)
}

val distinctPackages: Seq[PackageEntry] = if (packages == null) Nil else packages.toArray(new Array[PackageEntry](packages.size()))
val distinctClassesAndSources = mergeClassesAndSources(classesAndSourcesBuffer)
ClassPathEntries(distinctPackages, distinctClassesAndSources)
}

Expand All @@ -99,14 +112,12 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
* creates an entry containing both of them. If there would be more than one class or source
* entries for the same class it always would use the first entry of each type found on a classpath.
*/
private def mergeClassesAndSources(entries: Seq[Seq[ClassRepresentation]]): Seq[ClassRepresentation] = {
private def mergeClassesAndSources(entries: Seq[ClassRepresentation]): Seq[ClassRepresentation] = {
var count = 0
val indices = collection.mutable.HashMap[String, Int]()
val mergedEntries = new ArrayBuffer[ClassRepresentation](1024)

val mergedEntries = new ArrayBuffer[ClassRepresentation](entries.size)
for {
partOfEntries <- entries
entry <- partOfEntries
entry <- entries
} {
val name = entry.name
if (indices contains name) {
Expand Down
19 changes: 17 additions & 2 deletions src/compiler/scala/tools/nsc/classpath/ClassPath.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ trait SourceFileEntry extends ClassRepresentation {
def file: AbstractFile
}

case class PackageName(dottedString: String) {
def isRoot: Boolean = dottedString.isEmpty
val dirPathTrailingSlash: String = FileUtils.dirPath(dottedString) + "/"

def entryName(entry: String): String = {
if (isRoot) entry else {
val builder = new java.lang.StringBuilder(dottedString.length + 1 + entry.length)
builder.append(dottedString)
builder.append('.')
builder.append(entry)
builder.toString
}
}
}

trait PackageEntry {
def name: String
}
Expand Down Expand Up @@ -61,10 +76,10 @@ private[nsc] case class PackageEntryImpl(name: String) extends PackageEntry

private[nsc] trait NoSourcePaths {
final def asSourcePathString: String = ""
final private[nsc] def sources(inPackage: String): Seq[SourceFileEntry] = Seq.empty
final private[nsc] def sources(inPackage: PackageName): Seq[SourceFileEntry] = Seq.empty
}

private[nsc] trait NoClassPaths {
final def findClassFile(className: String): Option[AbstractFile] = None
private[nsc] final def classes(inPackage: String): Seq[ClassFileEntry] = Seq.empty
private[nsc] final def classes(inPackage: PackageName): Seq[ClassFileEntry] = Seq.empty
}
Loading