Skip to content

Commit 57f1527

Browse files
authored
Merge pull request #56 from scala/backport-lts-3.3-21753
Backport "Fix scala#9879: allow top-level opaque type definitions in REPL" to 3.3 LTS
2 parents 6b9084d + 8845080 commit 57f1527

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -4377,7 +4377,7 @@ object Parsers {
43774377
* | Expr1
43784378
* |
43794379
*/
4380-
def blockStatSeq(): List[Tree] = checkNoEscapingPlaceholders {
4380+
def blockStatSeq(outermost: Boolean = false): List[Tree] = checkNoEscapingPlaceholders {
43814381
val stats = new ListBuffer[Tree]
43824382
while
43834383
var empty = false
@@ -4389,7 +4389,11 @@ object Parsers {
43894389
stats += closure(in.offset, Location.InBlock, modifiers(BitSet(IMPLICIT)))
43904390
else if isIdent(nme.extension) && followingIsExtension() then
43914391
stats += extension()
4392-
else if isDefIntro(localModifierTokens, excludedSoftModifiers = Set(nme.`opaque`)) then
4392+
else if isDefIntro(localModifierTokens,
4393+
excludedSoftModifiers =
4394+
// Allow opaque definitions at outermost level in REPL.
4395+
if outermost && ctx.mode.is(Mode.Interactive)
4396+
then Set.empty else Set(nme.`opaque`)) then
43934397
stats +++= localDef(in.offset)
43944398
else
43954399
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

+28
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,34 @@ class ReplCompilerTests extends ReplTest:
372372
assertTrue(last, last.startsWith("val res0: tpolecat.type = null"))
373373
assertTrue(last, last.endsWith("""// result of "res0.toString" is null"""))
374374

375+
@Test def `i9879`: Unit = initially:
376+
run {
377+
"""|opaque type A = Int; def getA: A = 0
378+
|object Wrapper { opaque type A = Int; def getA: A = 1 }
379+
|val x = getA
380+
|val y = Wrapper.getA""".stripMargin
381+
}
382+
val expected = List(
383+
"def getA: A",
384+
"// defined object Wrapper",
385+
"val x: A = 0",
386+
"val y: Wrapper.A = 1"
387+
)
388+
assertEquals(expected, lines())
389+
390+
@Test def `i9879b`: Unit = initially:
391+
run {
392+
"""|def test =
393+
| type A = Int
394+
| opaque type B = String
395+
| object Wrapper { opaque type C = Int }
396+
| ()""".stripMargin
397+
}
398+
val all = lines()
399+
assertEquals(6, all.length)
400+
assertTrue(all.head.startsWith("-- [E103] Syntax Error"))
401+
assertTrue(all.exists(_.trim().startsWith("| Illegal start of statement: this modifier is not allowed here")))
402+
375403
object ReplCompilerTests:
376404

377405
private val pattern = Pattern.compile("\\r[\\n]?|\\n");

0 commit comments

Comments
 (0)