From d94b08ae02f0d496346321b11e2a17ba761454d6 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Thu, 5 Dec 2019 19:25:20 +0100 Subject: [PATCH 1/2] sourcepath: fix handling of top-level definitions 5c2a2d5652cc1ab22e1338226bf49377c98caa5d was a bit too clever: instead of running the desugaring of top-level definitions, it manually checked if such a desugaring was needed and then entered the package object if needed and traversed the non-desugared package statements, but in a situation like this: package foo type Foo object Foo The desugaring will move `object Foo` inside the package object, so by traversing the non-desugared tree, we were creating a symbol for Foo at the wrong level. This commit fixes this by simply calling the appropriate desugaring method before doing any traversal. Unfortunately I wasn't able to manufacture a testcase where this makes a difference, but this fixes some issues I saw when compiling dotty-library itself. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 6 ------ .../src/dotty/tools/dotc/core/SymbolLoaders.scala | 13 +++++++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 76f8a52ca76c..fefd7cfefaf3 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1229,12 +1229,6 @@ object desugar { case _ => false - /** Does this package contains at least one top-level definition - * that will require a wrapping object ? - */ - def hasTopLevelDef(pdef: PackageDef)(given Context): Boolean = - pdef.stats.exists(isTopLevelDef) - /** Assuming `src` contains top-level definition, returns the name that should * be using for the package object that will wrap them. */ diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index a7f16659dd62..4735e5a32c1b 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -18,7 +18,7 @@ import ast.Trees._ import parsing.JavaParsers.OutlineJavaParser import parsing.Parsers.OutlineParser import reporting.trace -import ast.desugar.{ packageObjectName, hasTopLevelDef } +import ast.desugar object SymbolLoaders { import ast.untpd._ @@ -135,11 +135,16 @@ object SymbolLoaders { ok } - def traverse(tree: Tree, path: List[TermName]): Unit = tree match { + /** Run the subset of desugaring necessary to record the correct symbols */ + def simpleDesugar(tree: Tree): Tree = tree match + case tree: PackageDef => + desugar.packageDef(tree) + case _ => + tree + + def traverse(tree: Tree, path: List[TermName]): Unit = simpleDesugar(tree) match { case tree @ PackageDef(pid, body) => val path1 = addPrefix(pid, path) - if hasTopLevelDef(tree) && checkPathMatches(path1, "package", pid) - enterModule(owner, packageObjectName(unit.source), completer, scope = scope) for (stat <- body) traverse(stat, path1) case tree: TypeDef if tree.isClassDef => if (checkPathMatches(path, "class", tree)) From d4b2222732c9f7e559cba94a696cc0afc889a472 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Thu, 5 Dec 2019 20:09:58 +0100 Subject: [PATCH 2/2] sourcepath: handle user-written package objects Turns out we never handled this properly before. --- .../src/dotty/tools/dotc/ast/Desugar.scala | 22 ++++++++++++++++++- .../dotty/tools/dotc/core/SymbolLoaders.scala | 2 ++ .../sourcepath/outer/nested2/package.scala | 5 +++++ tests/pos-special/sourcepath/outer/pkg.scala | 5 +++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/pos-special/sourcepath/outer/nested2/package.scala create mode 100644 tests/pos-special/sourcepath/outer/pkg.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index fefd7cfefaf3..3c13cdd4244e 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -804,6 +804,26 @@ object desugar { flatTree(cdef1 :: companions ::: implicitWrappers) }.reporting(i"desugared: $result", Printers.desugar) + /** Expand + * + * package object name { body } + * + * to: + * + * package name { + * object `package` { body } + * } + */ + def packageModuleDef(mdef: ModuleDef)(implicit ctx: Context): Tree = + val impl = mdef.impl + val mods = mdef.mods + val moduleName = normalizeName(mdef, impl).asTermName + if (mods.is(Package)) + PackageDef(Ident(moduleName), + cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil) + else + mdef + /** Expand * * object name extends parents { self => body } @@ -854,7 +874,7 @@ object desugar { ctx.warning(em"${hl("final")} modifier is redundant for objects", flagSourcePos(Final)) if (mods.is(Package)) - PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil) + packageModuleDef(mdef) else if (isEnumCase) { typeParamIsReferenced(enumClass.typeParams, Nil, Nil, impl.parents) // used to check there are no illegal references to enum's type parameters in parents diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 4735e5a32c1b..e4970b430506 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -139,6 +139,8 @@ object SymbolLoaders { def simpleDesugar(tree: Tree): Tree = tree match case tree: PackageDef => desugar.packageDef(tree) + case tree: ModuleDef => + desugar.packageModuleDef(tree) case _ => tree diff --git a/tests/pos-special/sourcepath/outer/nested2/package.scala b/tests/pos-special/sourcepath/outer/nested2/package.scala new file mode 100644 index 000000000000..85c59d0ce68c --- /dev/null +++ b/tests/pos-special/sourcepath/outer/nested2/package.scala @@ -0,0 +1,5 @@ +package outer + +package object nested2 { + val x: Int = 1 +} diff --git a/tests/pos-special/sourcepath/outer/pkg.scala b/tests/pos-special/sourcepath/outer/pkg.scala new file mode 100644 index 000000000000..46663d4f69e3 --- /dev/null +++ b/tests/pos-special/sourcepath/outer/pkg.scala @@ -0,0 +1,5 @@ +package outer + +object pkg { + val y: Int = nested2.x +}