Skip to content

Commit 658edd7

Browse files
authored
Fix #9879: allow top-level opaque type definitions in REPL (#21753)
2 parents 6e32627 + 3a98a1c commit 658edd7

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

Diff for: compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -4684,7 +4684,7 @@ object Parsers {
46844684
* | Expr1
46854685
* |
46864686
*/
4687-
def blockStatSeq(): List[Tree] = checkNoEscapingPlaceholders {
4687+
def blockStatSeq(outermost: Boolean = false): List[Tree] = checkNoEscapingPlaceholders {
46884688
val stats = new ListBuffer[Tree]
46894689
while
46904690
var empty = false
@@ -4696,7 +4696,11 @@ object Parsers {
46964696
stats += closure(in.offset, Location.InBlock, modifiers(BitSet(IMPLICIT)))
46974697
else if isIdent(nme.extension) && followingIsExtension() then
46984698
stats += extension()
4699-
else if isDefIntro(localModifierTokens, excludedSoftModifiers = Set(nme.`opaque`)) then
4699+
else if isDefIntro(localModifierTokens,
4700+
excludedSoftModifiers =
4701+
// Allow opaque definitions at outermost level in REPL.
4702+
if outermost && ctx.mode.is(Mode.Interactive)
4703+
then Set.empty else Set(nme.`opaque`)) then
47004704
stats +++= localDef(in.offset)
47014705
else
47024706
empty = true

Diff for: compiler/src/dotty/tools/repl/ParseResult.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ object ParseResult {
122122

123123
private def parseStats(using Context): List[untpd.Tree] = {
124124
val parser = new Parser(ctx.source)
125-
val stats = parser.blockStatSeq()
125+
val stats = parser.blockStatSeq(outermost = true)
126126
parser.accept(Tokens.EOF)
127127
stats
128128
}

Diff for: compiler/test/dotty/tools/repl/ReplCompilerTests.scala

+27-1
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,36 @@ class ReplCompilerTests extends ReplTest:
462462
.andThen:
463463
run("0") // check for crash
464464
val last = lines()
465-
println(last)
466465
assertTrue(last(0), last(0) == ("Options incompatible with repl will be ignored: -Ybest-effort, -Ywith-best-effort-tasty"))
467466
assertTrue(last(1), last(1) == ("val res0: Int = 0"))
468467

468+
@Test def `i9879`: Unit = initially:
469+
run {
470+
"""|opaque type A = Int; def getA: A = 0
471+
|object Wrapper { opaque type A = Int; def getA: A = 1 }
472+
|val x = getA
473+
|val y = Wrapper.getA""".stripMargin
474+
}
475+
val expected = List(
476+
"def getA: A",
477+
"// defined object Wrapper",
478+
"val x: A = 0",
479+
"val y: Wrapper.A = 1"
480+
)
481+
assertEquals(expected, lines())
482+
483+
@Test def `i9879b`: Unit = initially:
484+
run {
485+
"""|def test =
486+
| type A = Int
487+
| opaque type B = String
488+
| object Wrapper { opaque type C = Int }
489+
| ()""".stripMargin
490+
}
491+
val all = lines()
492+
assertEquals(6, all.length)
493+
assertTrue(all.head.startsWith("-- [E103] Syntax Error"))
494+
assertTrue(all.exists(_.trim().startsWith("| Illegal start of statement: this modifier is not allowed here")))
469495

470496
object ReplCompilerTests:
471497

0 commit comments

Comments
 (0)