aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/typer/Namer.scala
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2017-03-28 18:49:19 +0200
committerGuillaume Martres <smarter@ubuntu.com>2017-03-29 18:31:31 +0200
commit466065a0db976f644149625237af0544d9fe16fa (patch)
tree2188923b63d20cb92140207d33da75d17691cbff /compiler/src/dotty/tools/dotc/typer/Namer.scala
parentf49c10d1667de897b2073d9b15c7c6cb8cc52482 (diff)
downloaddotty-466065a0db976f644149625237af0544d9fe16fa.tar.gz
dotty-466065a0db976f644149625237af0544d9fe16fa.tar.bz2
dotty-466065a0db976f644149625237af0544d9fe16fa.zip
Create dummy companions for classes without a real one
In #2139 I added code to create dummy companions for companion-less objects, but not for companion-less classes because I thought it wasn't needed. But it turns out that even if the classpath only has `Foo.class` and not `Foo$.class`, a module for `Foo` is entered by `initializeFromClassPath` when it calls `enterClassAndModule`, so we have to add dummy companions to classes. I don't have a test to illustrate this issue, but note that it fixes the incremental compilation bug demonstrated by https://github.com/dotty-staging/dotty/commits/incremental-compilation-bug. Note: I verified that adding a dummy companion to "class Foo" did not cause the backend to emit a Foo$.class, so this should have no visible impact.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer/Namer.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala21
1 files changed, 16 insertions, 5 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala
index 4077d8d65..94506f318 100644
--- a/compiler/src/dotty/tools/dotc/typer/Namer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala
@@ -606,11 +606,11 @@ class Namer { typer: Typer =>
}
}
- // If a top-level object has no companion class in the current run, we
- // enter a dummy companion class symbol (`denot.isAbsent` returns true) in
- // scope. This ensures that we never use a companion from a previous run
- // or from the classpath. See tests/pos/false-companion for an
- // example where this matters.
+ // If a top-level object or class has no companion in the current run, we
+ // enter a dummy companion (`denot.isAbsent` returns true) in scope. This
+ // ensures that we never use a companion from a previous run or from the
+ // classpath. See tests/pos/false-companion for an example where this
+ // matters.
if (ctx.owner.is(PackageClass)) {
for (cdef @ TypeDef(moduleName, _) <- moduleDef.values) {
val moduleSym = ctx.effectiveScope.lookup(moduleName.encode)
@@ -623,6 +623,17 @@ class Namer { typer: Typer =>
}
}
}
+ for (cdef @ TypeDef(className, _) <- classDef.values) {
+ val classSym = ctx.effectiveScope.lookup(className.encode)
+ if (classSym.isDefinedInCurrentRun) {
+ val moduleName = className.toTermName
+ val moduleSym = ctx.effectiveScope.lookup(moduleName.encode)
+ if (!moduleSym.isDefinedInCurrentRun) {
+ val absentModuleSymbol = ctx.newModuleSymbol(ctx.owner, moduleName, EmptyFlags, EmptyFlags, (_, _) => NoType)
+ enterSymbol(absentModuleSymbol)
+ }
+ }
+ }
}
}