Skip to content

Commit 5fcc131

Browse files
committed
Incremental compilation: handle constructor proxies
I noticed that repeatedly runnning `sbt compile` in dotty lead to the same files being compiled over and over even though nothing changed, running `sbt "debug; compile"` revealed messages like this: [debug] Invalidating '${BASE}/compiler/target/scala-3.0.0-RC1/classes/dotty/tools/dotc/typer/Namer.class' because could not find class dotty.tools.dotc.typer.Namer$ on the classpath. Indeed, Namer does not have a companion object so there's no `Namer$.class` file, but sbt was looking for one because we registered such a companion with `ctx.sbtCallback.binaryDependency`, this happened because we created a fake companion object for the purpose of holding constructor proxies (fake apply methods that forward to a constructor). The fix is to special-case such references, just like we already special-cased references to the fake companion of Java classes.
1 parent 3c837f9 commit 5fcc131

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,19 @@ class ExtractDependencies extends Phase {
150150
builder.append(".")
151151
}
152152
val flatName = dep.to.flatName
153-
// We create fake companion object symbols to hold the static members
154-
// of Java classes, make sure to use the name of the actual Java class
155-
// here.
156-
val clsFlatName = if (dep.to.is(JavaDefined)) flatName.stripModuleClassSuffix else flatName
153+
// Some companion objects are fake (that is, they're a compiler fiction
154+
// that doesn't correspond to a class that exists at runtime), this
155+
// can happen in two cases:
156+
// - If a Java class has static members.
157+
// - If we create constructor proxies for a class (see NamerOps#addConstructorProxies).
158+
//
159+
// In both cases it's vital that we don't send the object name to
160+
// zinc: when sbt is restarted, zinc will inspect the binary
161+
// dependencies to see if they're still on the classpath, if it
162+
// doesn't find them it will invalidate whatever referenced them, so
163+
// any reference to a fake companion will lead to extra recompilations.
164+
// Instead, use the class name since it's guaranteed to exist at runtime.
165+
val clsFlatName = if (dep.to.isOneOf(JavaDefined | ConstructorProxy)) flatName.stripModuleClassSuffix else flatName
157166
builder.append(clsFlatName.mangledString)
158167
builder.toString
159168
}

0 commit comments

Comments
 (0)