Skip to content

Commit 6ef28df

Browse files
committed
Dedupe sym.binaryClassName
1 parent 41a584a commit 6ef28df

File tree

4 files changed

+27
-42
lines changed

4 files changed

+27
-42
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,30 @@ object SymDenotations {
505505
/** `fullName` where `.' is the separator character */
506506
def fullName(using Context): Name = fullNameSeparated(QualifiedName)
507507

508+
/** The fully qualified name on the JVM of the class corresponding to this symbol. */
509+
def binaryClassName(using Context): String =
510+
val builder = new StringBuilder
511+
val pkg = enclosingPackageClass
512+
if !pkg.isEffectiveRoot then
513+
builder.append(pkg.fullName.mangledString)
514+
builder.append(".")
515+
val flatName = this.flatName
516+
// Some companion objects are fake (that is, they're a compiler fiction
517+
// that doesn't correspond to a class that exists at runtime), this
518+
// can happen in two cases:
519+
// - If a Java class has static members.
520+
// - If we create constructor proxies for a class (see NamerOps#addConstructorProxies).
521+
//
522+
// In both cases it's may be vital that we don't return the object name.
523+
// For instance, sending it to zinc: when sbt is restarted, zinc will inspect the binary
524+
// dependencies to see if they're still on the classpath, if it
525+
// doesn't find them it will invalidate whatever referenced them, so
526+
// any reference to a fake companion will lead to extra recompilations.
527+
// Instead, use the class name since it's guaranteed to exist at runtime.
528+
val clsFlatName = if isOneOf(JavaDefined | ConstructorProxy) then flatName.stripModuleClassSuffix else flatName
529+
builder.append(clsFlatName.mangledString)
530+
builder.toString
531+
508532
private var myTargetName: Name | Null = null
509533

510534
private def computeTargetName(targetNameAnnot: Option[Annotation])(using Context): Name =

compiler/src/dotty/tools/dotc/quoted/Interpreter.scala

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,7 @@ abstract class Interpreter(pos: SrcPos, classLoader: ClassLoader)(using Context)
200200
}
201201
else {
202202
// nested object in an object
203-
val className = {
204-
val pack = sym.topLevelClass.owner
205-
if (pack == defn.RootPackage || pack == defn.EmptyPackageClass) sym.flatName.toString
206-
else pack.showFullName + "." + sym.flatName
207-
}
208-
val clazz = loadClass(className)
203+
val clazz = loadClass(sym.binaryClassName)
209204
clazz.getConstructor().newInstance().asInstanceOf[Object]
210205
}
211206

compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -143,34 +143,7 @@ class ExtractDependencies extends Phase {
143143
def allowLocal = dep.context == DependencyByInheritance || dep.context == LocalDependencyByInheritance
144144
if (depFile.extension == "class") {
145145
// Dependency is external -- source is undefined
146-
147-
// The fully qualified name on the JVM of the class corresponding to `dep.to`
148-
val binaryClassName = {
149-
val builder = new StringBuilder
150-
val pkg = dep.to.enclosingPackageClass
151-
if (!pkg.isEffectiveRoot) {
152-
builder.append(pkg.fullName.mangledString)
153-
builder.append(".")
154-
}
155-
val flatName = dep.to.flatName
156-
// Some companion objects are fake (that is, they're a compiler fiction
157-
// that doesn't correspond to a class that exists at runtime), this
158-
// can happen in two cases:
159-
// - If a Java class has static members.
160-
// - If we create constructor proxies for a class (see NamerOps#addConstructorProxies).
161-
//
162-
// In both cases it's vital that we don't send the object name to
163-
// zinc: when sbt is restarted, zinc will inspect the binary
164-
// dependencies to see if they're still on the classpath, if it
165-
// doesn't find them it will invalidate whatever referenced them, so
166-
// any reference to a fake companion will lead to extra recompilations.
167-
// Instead, use the class name since it's guaranteed to exist at runtime.
168-
val clsFlatName = if (dep.to.isOneOf(JavaDefined | ConstructorProxy)) flatName.stripModuleClassSuffix else flatName
169-
builder.append(clsFlatName.mangledString)
170-
builder.toString
171-
}
172-
173-
processExternalDependency(depFile, binaryClassName)
146+
processExternalDependency(depFile, dep.to.binaryClassName)
174147
} else if (allowLocal || depFile.file != sourceFile) {
175148
// We cannot ignore dependencies coming from the same source file because
176149
// the dependency info needs to propagate. See source-dependencies/trait-trait-211.

compiler/src/dotty/tools/repl/Rendering.scala

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,7 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None):
130130
*/
131131
private def rewrapValueClass(sym: Symbol, value: Object)(using Context): Option[Object] =
132132
if ValueClasses.isDerivedValueClass(sym) then
133-
val pkg = sym.enclosingPackageClass
134-
val pkgName = if pkg.isEmptyPackage then "" else s"${pkg.fullName.mangledString}."
135-
val clsFlatName = if sym.isOneOf(JavaDefined | ConstructorProxy) then
136-
// See ExtractDependencies.recordDependency
137-
sym.flatName.stripModuleClassSuffix
138-
else sym.flatName
139-
val valueClassName = pkgName + clsFlatName.mangledString
140-
val valueClass = Class.forName(valueClassName, true, classLoader())
133+
val valueClass = Class.forName(sym.binaryClassName, true, classLoader())
141134
valueClass.getConstructors.headOption.map(_.newInstance(value))
142135
else
143136
Some(value)

0 commit comments

Comments
 (0)