From 8a28ce40a1db5dc51c4466e9fa21993b60d15310 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 21 Nov 2022 23:33:09 +0000 Subject: [PATCH] Fix REPL shadowing bug --- .../tools/dotc/printing/RefinedPrinter.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 9 +++++++-- .../src/dotty/tools/repl/ReplCompiler.scala | 1 - .../dotty/tools/repl/ShadowingBatchTests.scala | 14 ++++++++++++++ .../test/dotty/tools/repl/ShadowingTests.scala | 17 +++++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 62e1cd5baec8..568f7e271af6 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -1060,7 +1060,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (sym.isImport) sym.infoOrCompleter match { case info: Namer#Completer => return info.original.show - case info: ImportType => return s"import $info.expr.show" + case info: ImportType => return s"import ${info.expr.show}" case _ => } def name = diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 032bed38482c..245bd490af20 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -439,7 +439,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if (curImport.nn.unimported ne NoSymbol) unimported += curImport.nn.unimported if (curOwner.is(Package) && curImport != null && curImport.isRootImport && previous.exists) previous // no more conflicts possible in this case - else if (isPossibleImport(NamedImport) && (curImport nen outer.importInfo)) { + else if isPossibleImport(NamedImport) && + ((curImport nen outer.importInfo) + || curImport != null + && curImport.isRootImport + && curImport.site.termSymbol.name.isReplWrapperName + ) + then val namedImp = namedImportRef(curImport.uncheckedNN) if (namedImp.exists) recurAndCheckNewOrShadowed(namedImp, NamedImport, ctx)(using outer) @@ -456,7 +462,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer updateUnimported() loop(ctx)(using outer) } - } else loop(ctx)(using outer) } } diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 8db288f50aca..69bd97148d73 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -62,7 +62,6 @@ class ReplCompiler extends Compiler: } val rootCtx = super.rootContext.fresh - .setOwner(defn.EmptyPackageClass) .withRootImports (state.validObjectIndexes).foldLeft(rootCtx)((ctx, id) => importPreviousRun(id)(using ctx)) diff --git a/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala b/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala index 5a96976bd867..7272c10aa003 100644 --- a/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala +++ b/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala @@ -32,6 +32,20 @@ class ShadowingBatchTests extends ErrorMessagesTest: ictx.setSetting(classpath, classpath.value + File.pathSeparator + dir.jpath.toAbsolutePath) } + @Test def io = + val lib = """|package io.foo + | + |object Bar { + | def baz: Int = 42 + |} + |""".stripMargin + val app = """|object Main: + | def main(args: Array[String]): Unit = + | println(io.foo.Bar.baz) + |""".stripMargin + checkMessages(lib).expectNoErrors + checkMessages(app).expectNoErrors + @Test def file = checkMessages("class C(val c: Int)").expectNoErrors checkMessages("object rsline1 {\n def line1 = new C().c\n}").expect { (_, msgs) => diff --git a/compiler/test/dotty/tools/repl/ShadowingTests.scala b/compiler/test/dotty/tools/repl/ShadowingTests.scala index 457819966346..98aa58a62a15 100644 --- a/compiler/test/dotty/tools/repl/ShadowingTests.scala +++ b/compiler/test/dotty/tools/repl/ShadowingTests.scala @@ -76,6 +76,18 @@ class ShadowingTests extends ReplTest(options = ShadowingTests.options): Files.delete(file) end compileShadowed + @Test def io = shadowedScriptedTest(name = "io", + shadowed = """|package io.foo + | + |object Bar { + | def baz: Int = 42 + |} + |""".stripMargin, + script = """|scala> io.foo.Bar.baz + |val res0: Int = 42 + |""".stripMargin + ) + @Test def i7635 = shadowedScriptedTest(name = "", shadowed = "class C(val c: Int)", script = @@ -129,6 +141,11 @@ class ShadowingTests extends ReplTest(options = ShadowingTests.options): ShadowingTests.createSubDir("util") testScript(name = "", """|scala> import util.Try + |-- [E008] Not Found Error: ----------------------------------------------------- + |1 | import util.Try + | | ^^^ + | | value Try is not a member of util + |1 error found | |scala> object util { class Try { override def toString = "you've gotta try!" } } |// defined object util