From 8539117435529c1aeaef3ef6e95bdaef24cb23c3 Mon Sep 17 00:00:00 2001 From: Anatolii Kmetiuk Date: Thu, 4 Apr 2019 16:46:26 +0200 Subject: [PATCH] Fix #5897 and fix #6200: implicits not retained in REPL When evaluating definitions in REPL (`def`, `implied` etc), they are brought in scope for all the subsequent evaluations of the user input. This is done via the `import` mechanism. However, in Dotty, the semantics of the imports changed: by default, the implied values are not imported. This commit makes sure that all the members, including the implied ones, are imported from the previous evaluations of the input. --- .../dotty/tools/dotc/typer/ImportInfo.scala | 6 +-- .../src/dotty/tools/repl/ReplCompiler.scala | 9 +++-- .../dotty/tools/repl/ReplCompilerTests.scala | 38 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala index 33e02fd349a0..68942b75f807 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -13,11 +13,11 @@ import printing.Texts.Text object ImportInfo { /** The import info for a root import from given symbol `sym` */ - def rootImport(refFn: () => TermRef)(implicit ctx: Context): ImportInfo = { + def rootImport(refFn: () => TermRef, importImplied: Boolean = false)(implicit ctx: Context): ImportInfo = { val selectors = untpd.Ident(nme.WILDCARD) :: Nil def expr(implicit ctx: Context) = tpd.Ident(refFn()) - def imp(implicit ctx: Context) = tpd.Import(importImplied = false, expr, selectors) - new ImportInfo(implicit ctx => imp.symbol, selectors, None, importImplied = false, isRootImport = true) + def imp(implicit ctx: Context) = tpd.Import(importImplied = importImplied, expr, selectors) + new ImportInfo(implicit ctx => imp.symbol, selectors, None, importImplied = importImplied, isRootImport = true) } } diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 3c4f38cc6170..4641633cd132 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -48,9 +48,12 @@ class ReplCompiler extends Compiler { def importPreviousRun(id: Int)(implicit ctx: Context) = { // we first import the wrapper object id val path = nme.EMPTY_PACKAGE ++ "." ++ objectNames(id) - val importInfo = ImportInfo.rootImport(() => - ctx.requiredModuleRef(path)) - val ctx0 = ctx.fresh.setNewScope.setImportInfo(importInfo) + def importWrapper(c: Context, importImplied: Boolean) = { + val importInfo = ImportInfo.rootImport(() => + c.requiredModuleRef(path), importImplied) + c.fresh.setNewScope.setImportInfo(importInfo) + } + val ctx0 = importWrapper(importWrapper(ctx, false), true) // then its user defined imports val imports = state.imports.getOrElse(id, Nil) diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index 85d757f939ae..f1c41b54c55a 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -127,4 +127,42 @@ class ReplCompilerTests extends ReplTest { run(source) assertEquals(expected, lines()) } + + @Test def i5897 = + fromInitialState { implicit state => run("implied for Int = 10") } + .andThen { implicit state => + assertEquals( + "def Int_instance: Int", + storedOutput().trim + ) + run("implicitly[Int]") + assertEquals( + "val res0: Int = 10", + storedOutput().trim + ) + } + + @Test def i6200 = + fromInitialState { implicit state => + run(""" + |trait Ord[T] { + | def compare(x: T, y: T): Int + | def (x: T) < (y: T) = compare(x, y) < 0 + | def (x: T) > (y: T) = compare(x, y) > 0 + |} + | + |implied IntOrd for Ord[Int] { + | def compare(x: Int, y: Int) = + | if (x < y) -1 else if (x > y) +1 else 0 + |} + """.stripMargin) } + .andThen { implicit state => + assertEquals( + """// defined trait Ord + |// defined object IntOrd""".stripMargin, + storedOutput().trim + ) + run("IntOrd") + assertTrue(storedOutput().startsWith("val res0: IntOrd.type =")) + } }