Skip to content

Commit

Permalink
Fix #9879: allow top-level opaque type definitions in REPL (#21753)
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored Oct 22, 2024
2 parents 6e32627 + 3a98a1c commit 658edd7
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4684,7 +4684,7 @@ object Parsers {
* | Expr1
* |
*/
def blockStatSeq(): List[Tree] = checkNoEscapingPlaceholders {
def blockStatSeq(outermost: Boolean = false): List[Tree] = checkNoEscapingPlaceholders {
val stats = new ListBuffer[Tree]
while
var empty = false
Expand All @@ -4696,7 +4696,11 @@ object Parsers {
stats += closure(in.offset, Location.InBlock, modifiers(BitSet(IMPLICIT)))
else if isIdent(nme.extension) && followingIsExtension() then
stats += extension()
else if isDefIntro(localModifierTokens, excludedSoftModifiers = Set(nme.`opaque`)) then
else if isDefIntro(localModifierTokens,
excludedSoftModifiers =
// Allow opaque definitions at outermost level in REPL.
if outermost && ctx.mode.is(Mode.Interactive)
then Set.empty else Set(nme.`opaque`)) then
stats +++= localDef(in.offset)
else
empty = true
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/repl/ParseResult.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ object ParseResult {

private def parseStats(using Context): List[untpd.Tree] = {
val parser = new Parser(ctx.source)
val stats = parser.blockStatSeq()
val stats = parser.blockStatSeq(outermost = true)
parser.accept(Tokens.EOF)
stats
}
Expand Down
28 changes: 27 additions & 1 deletion compiler/test/dotty/tools/repl/ReplCompilerTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -462,10 +462,36 @@ class ReplCompilerTests extends ReplTest:
.andThen:
run("0") // check for crash
val last = lines()
println(last)
assertTrue(last(0), last(0) == ("Options incompatible with repl will be ignored: -Ybest-effort, -Ywith-best-effort-tasty"))
assertTrue(last(1), last(1) == ("val res0: Int = 0"))

@Test def `i9879`: Unit = initially:
run {
"""|opaque type A = Int; def getA: A = 0
|object Wrapper { opaque type A = Int; def getA: A = 1 }
|val x = getA
|val y = Wrapper.getA""".stripMargin
}
val expected = List(
"def getA: A",
"// defined object Wrapper",
"val x: A = 0",
"val y: Wrapper.A = 1"
)
assertEquals(expected, lines())

@Test def `i9879b`: Unit = initially:
run {
"""|def test =
| type A = Int
| opaque type B = String
| object Wrapper { opaque type C = Int }
| ()""".stripMargin
}
val all = lines()
assertEquals(6, all.length)
assertTrue(all.head.startsWith("-- [E103] Syntax Error"))
assertTrue(all.exists(_.trim().startsWith("| Illegal start of statement: this modifier is not allowed here")))

object ReplCompilerTests:

Expand Down

0 comments on commit 658edd7

Please sign in to comment.