From ecccfc9631a97c94a0c23e7beab181ff84462a7c Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 16 Dec 2024 14:04:38 +0000 Subject: [PATCH 1/4] Add hint when found cc language import in repl --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 89f88faebc17..8e5de37a4e20 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3706,7 +3706,11 @@ object Parsers { in.languageImportContext = in.languageImportContext.importContext(imp, NoSymbol) for case ImportSelector(id @ Ident(imported), EmptyTree, _) <- selectors do if Feature.handleGlobalLanguageImport(prefix, imported) && !outermost then - syntaxError(em"this language import is only allowed at the toplevel", id.span) + val hint = + if ctx.mode.is(Mode.Interactive) then + f"\nTo use this language feature, include the flag `-language:$prefix.$imported` when starting the REPL" + else "" + syntaxError(em"this language import is only allowed at the toplevel$hint", id.span) if allSourceVersionNames.contains(imported) && prefix.isEmpty then if !outermost then syntaxError(em"source version import is only allowed at the toplevel", id.span) From 958371ccb20ad55612d241f71a43e3063dec6328 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 16 Dec 2024 14:06:00 +0000 Subject: [PATCH 2/4] Refine the hint --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 8e5de37a4e20..eb277edcfbce 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3706,11 +3706,15 @@ object Parsers { in.languageImportContext = in.languageImportContext.importContext(imp, NoSymbol) for case ImportSelector(id @ Ident(imported), EmptyTree, _) <- selectors do if Feature.handleGlobalLanguageImport(prefix, imported) && !outermost then + val location = + if ctx.mode.is(Mode.Interactive) then + "in the REPL" + else "at the toplevel" val hint = if ctx.mode.is(Mode.Interactive) then f"\nTo use this language feature, include the flag `-language:$prefix.$imported` when starting the REPL" else "" - syntaxError(em"this language import is only allowed at the toplevel$hint", id.span) + syntaxError(em"this language import is only allowed $location$hint", id.span) if allSourceVersionNames.contains(imported) && prefix.isEmpty then if !outermost then syntaxError(em"source version import is only allowed at the toplevel", id.span) From 2e409e1f50796e2e869c32f4f551f4d0d7a97115 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 16 Dec 2024 21:09:24 +0100 Subject: [PATCH 3/4] Fix the description --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index eb277edcfbce..e9f6b01a99c3 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3706,15 +3706,15 @@ object Parsers { in.languageImportContext = in.languageImportContext.importContext(imp, NoSymbol) for case ImportSelector(id @ Ident(imported), EmptyTree, _) <- selectors do if Feature.handleGlobalLanguageImport(prefix, imported) && !outermost then - val location = + val desc = if ctx.mode.is(Mode.Interactive) then - "in the REPL" - else "at the toplevel" + "not allowed in the REPL" + else "only allowed at the toplevel" val hint = if ctx.mode.is(Mode.Interactive) then f"\nTo use this language feature, include the flag `-language:$prefix.$imported` when starting the REPL" else "" - syntaxError(em"this language import is only allowed $location$hint", id.span) + syntaxError(em"this language import is $desc$hint", id.span) if allSourceVersionNames.contains(imported) && prefix.isEmpty then if !outermost then syntaxError(em"source version import is only allowed at the toplevel", id.span) From c79b2121bf11ffc2f8b668299c658bb2983bc55a Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 16 Dec 2024 21:09:35 +0100 Subject: [PATCH 4/4] Add repl tests --- .../dotty/tools/repl/ReplCompilerTests.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index 221eb8acb9de..d32b28647c32 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -493,6 +493,24 @@ class ReplCompilerTests extends ReplTest: assertTrue(all.head.startsWith("-- [E103] Syntax Error")) assertTrue(all.exists(_.trim().startsWith("| Illegal start of statement: this modifier is not allowed here"))) + @Test def `i16250a`: Unit = initially: + val hints = List( + "this language import is not allowed in the REPL", + "To use this language feature, include the flag `-language:experimental.captureChecking` when starting the REPL" + ) + run("import language.experimental.captureChecking") + val all = lines() + assertTrue(hints.forall(hint => all.exists(_.contains(hint)))) + + @Test def `i16250b`: Unit = initially: + val hints = List( + "this language import is not allowed in the REPL", + "To use this language feature, include the flag `-language:experimental.pureFunctions` when starting the REPL" + ) + run("import language.experimental.pureFunctions") + val all = lines() + assertTrue(hints.forall(hint => all.exists(_.contains(hint)))) + object ReplCompilerTests: private val pattern = Pattern.compile("\\r[\\n]?|\\n");