Skip to content

Commit 65455bb

Browse files
committed
Fix #2137: Create dummy companions for top-level objects without a real one
Previously, we sometimes ended up forcing a companion class symbol from a previous run or from the classpath which lead to weird issues like in `false-companion`. Even if we end up not forcing such a symbol, its presence can still lead to issue: before this commit incremental compilation of `dotty-compiler-bootstrapped` was broken because we recorded a false dependency on the non-bootstrapped `dotty-compiler` jar. The added test is currently marked pending because it does not work with JUnit (which doesn't handle separate compilation), only partest. I didn't managed to get it to work right, and this won't be necessary once our testing framework is overhauled by #2125 anyway, so I'll just have to remember to enable this test afterwards.
1 parent 6ab7c1d commit 65455bb

File tree

5 files changed

+36
-0
lines changed

5 files changed

+36
-0
lines changed

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,25 @@ class Namer { typer: Typer =>
605605
case EmptyTree =>
606606
}
607607
}
608+
609+
// If a top-level object has no companion class in the current run, we
610+
// enter a dummy companion class symbol (`denot.isAbsent` returns true) in
611+
// scope. This ensures that we never use a companion from a previous run
612+
// or from the classpath. See tests/pos/false-companion for an
613+
// example where this matters.
614+
if (ctx.owner.is(PackageClass)) {
615+
for (cdef @ TypeDef(moduleName, _) <- moduleDef.values) {
616+
val moduleSym = ctx.denotNamed(moduleName.encode).symbol
617+
if (moduleSym.isDefinedInCurrentRun) {
618+
val className = moduleName.stripModuleClassSuffix.toTypeName
619+
val classSym = ctx.denotNamed(className.encode).symbol
620+
if (!classSym.isDefinedInCurrentRun) {
621+
val absentClassSymbol = ctx.newClassSymbol(ctx.owner, className, EmptyFlags, _ => NoType)
622+
enterSymbol(absentClassSymbol)
623+
}
624+
}
625+
}
626+
}
608627
}
609628

610629
stats.foreach(expand)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package outer
2+
package inner
3+
object Test {
4+
val x: Foo = new Foo
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package outer
2+
package inner
3+
object Foo {
4+
// val a: Int = 1
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
package outer
2+
class Foo
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package outer
2+
package inner
3+
object Foo {
4+
val a: Int = 1
5+
}

0 commit comments

Comments
 (0)