diff options
6 files changed, 39 insertions, 3 deletions
diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index c392880c5..fefa63f6f 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -175,7 +175,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp override def traverse(tree: Tree)(implicit ctx: Context): Unit = { tree match { case Import(expr, selectors) => - def lookupImported(name: Name) = expr.tpe.select(name).typeSymbol + def lookupImported(name: Name) = expr.tpe.member(name).symbol def addImported(name: Name) = { // importing a name means importing both a term and a type (if they exist) addDependency(lookupImported(name.toTermName)) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2cefc52a0..4077d8d65 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -570,8 +570,8 @@ class Namer { typer: Typer => /** Create links between companion object and companion class */ def createLinks(classTree: TypeDef, moduleTree: TypeDef)(implicit ctx: Context) = { - val claz = ctx.denotNamed(classTree.name.encode).symbol - val modl = ctx.denotNamed(moduleTree.name.encode).symbol + val claz = ctx.effectiveScope.lookup(classTree.name.encode) + val modl = ctx.effectiveScope.lookup(moduleTree.name.encode) ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, claz, modl).entered ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, modl, claz).entered } @@ -605,6 +605,25 @@ class Namer { typer: Typer => case EmptyTree => } } + + // 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 (ctx.owner.is(PackageClass)) { + for (cdef @ TypeDef(moduleName, _) <- moduleDef.values) { + val moduleSym = ctx.effectiveScope.lookup(moduleName.encode) + if (moduleSym.isDefinedInCurrentRun) { + val className = moduleName.stripModuleClassSuffix.toTypeName + val classSym = ctx.effectiveScope.lookup(className.encode) + if (!classSym.isDefinedInCurrentRun) { + val absentClassSymbol = ctx.newClassSymbol(ctx.owner, className, EmptyFlags, _ => NoType) + enterSymbol(absentClassSymbol) + } + } + } + } } stats.foreach(expand) diff --git a/tests/pending/pos/false-companion/00_outerinnerTest_2.scala b/tests/pending/pos/false-companion/00_outerinnerTest_2.scala new file mode 100644 index 000000000..8f5802343 --- /dev/null +++ b/tests/pending/pos/false-companion/00_outerinnerTest_2.scala @@ -0,0 +1,5 @@ +package outer +package inner +object Test { + val x: Foo = new Foo +} diff --git a/tests/pending/pos/false-companion/01_outerinnerFoo_2.scala b/tests/pending/pos/false-companion/01_outerinnerFoo_2.scala new file mode 100644 index 000000000..111f7fcd5 --- /dev/null +++ b/tests/pending/pos/false-companion/01_outerinnerFoo_2.scala @@ -0,0 +1,5 @@ +package outer +package inner +object Foo { + // val a: Int = 1 +} diff --git a/tests/pending/pos/false-companion/outerFoo_1.scala b/tests/pending/pos/false-companion/outerFoo_1.scala new file mode 100644 index 000000000..8c2ef109c --- /dev/null +++ b/tests/pending/pos/false-companion/outerFoo_1.scala @@ -0,0 +1,2 @@ +package outer +class Foo diff --git a/tests/pending/pos/false-companion/outerinnerFoo_1.scala b/tests/pending/pos/false-companion/outerinnerFoo_1.scala new file mode 100644 index 000000000..29f3df724 --- /dev/null +++ b/tests/pending/pos/false-companion/outerinnerFoo_1.scala @@ -0,0 +1,5 @@ +package outer +package inner +object Foo { + val a: Int = 1 +} |