Skip to content

Commit 5bc83b9

Browse files
committed
Error tree on outdent is zero extent
Recovery on syntax error may consume remaining input, with an OUTDENT at EOF, so that the parent tree does not actually extend to EOF. Do not report spurious `def <error>` as ambiguous. [Cherry-picked 85c0527][modified]
1 parent ee01c47 commit 5bc83b9

File tree

5 files changed

+38
-3
lines changed

5 files changed

+38
-3
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,9 @@ object Parsers {
403403
false
404404
}
405405

406-
def errorTermTree(start: Offset): Tree = atSpan(Span(start, in.offset)) { unimplementedExpr }
406+
def errorTermTree(start: Offset): Tree =
407+
val end = if in.token == OUTDENT then start else in.offset
408+
atSpan(Span(start, end)) { unimplementedExpr }
407409

408410
private var inFunReturnType = false
409411
private def fromWithinReturnType[T](body: => T): T = {

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ object Scanners {
305305
println(s"\nSTART SKIP AT ${sourcePos().line + 1}, $this in $currentRegion")
306306
var noProgress = 0
307307
// Defensive measure to ensure we always get out of the following while loop
308-
// even if source file is weirly formatted (i.e. we never reach EOF)
308+
// even if source file is weirdly formatted (i.e. we never reach EOF)
309309
var prevOffset = offset
310310
while !atStop && noProgress < 3 do
311311
nextToken()

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,7 @@ trait Checking {
11751175
typr.println(i"check no double declarations $cls")
11761176

11771177
def checkDecl(decl: Symbol): Unit = {
1178-
for (other <- seen(decl.name) if !decl.isAbsent() && !other.isAbsent()) {
1178+
for (other <- seen(decl.name) if decl.name != nme.ERROR && !decl.isAbsent() && !other.isAbsent()) {
11791179
typr.println(i"conflict? $decl $other")
11801180
def javaFieldMethodPair =
11811181
decl.is(JavaDefined) && other.is(JavaDefined) &&

tests/neg/i23729.check

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- [E018] Syntax Error: tests/neg/i23729.scala:17:33 -------------------------------------------------------------------
2+
17 | def start: List[Direction] = match self // error syntax
3+
| ^^^^^
4+
| expression expected but match found
5+
|
6+
| longer explanation available when compiling with `-explain`
7+
-- [E040] Syntax Error: tests/neg/i23729.scala:18:6 --------------------------------------------------------------------
8+
18 | case Empty => Nil // error poor recovery
9+
| ^^^^
10+
| 'def' expected, but 'case' found
11+
-- [E040] Syntax Error: tests/neg/i23729.scala:19:6 --------------------------------------------------------------------
12+
19 | case Node(_, l, _) => l.start :+ Left // error poor recovery
13+
| ^^^^
14+
| 'def' expected, but 'case' found

tests/neg/i23729.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
trait Collection[Self, Element]:
3+
type Index
4+
extension (self: Self)
5+
def start: Index
6+
7+
sealed trait Tree[+T]
8+
object Tree:
9+
case object Empty extends Tree[Nothing]
10+
case class Node[+T](value: T, lhs: Tree[T], rhs: Tree[T]) extends Tree[T]
11+
12+
enum Direction:
13+
case Left, Right, Here
14+
given [T]: Collection[Tree[T], T] with
15+
type Index = List[Direction]
16+
extension (self: Tree[T])
17+
def start: List[Direction] = match self // error syntax
18+
case Empty => Nil // error poor recovery
19+
case Node(_, l, _) => l.start :+ Left // error poor recovery

0 commit comments

Comments
 (0)