diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2017-03-28 18:49:19 +0200 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2017-03-29 18:31:31 +0200 |
commit | 466065a0db976f644149625237af0544d9fe16fa (patch) | |
tree | 2188923b63d20cb92140207d33da75d17691cbff /compiler/src/dotty/tools/dotc/typer/Namer.scala | |
parent | f49c10d1667de897b2073d9b15c7c6cb8cc52482 (diff) | |
download | dotty-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.scala | 21 |
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) + } + } + } } } |