Skip to content

Commit dfff8f6

Browse files
authored
Make error reporting resilient to exception thrown while reporting (#20158)
Previously the added test failed with `1 error reported` but no actual error message printed, because a stack overflow is thrown while reporting the original error. This is then caught and handled to emit a RecursionOverflow error, but that second error is non-sensical and non-sensical errors are only printed if `hasErrors` returns false. We fix this by deferring incrementing the error count (and therefore having `hasErrors` return true) until after having displayed the error. We also defer calling `markReported` otherwise the second error will also be suppressed. A similar change is necessary in our testing infrastructure to keep the error count is coherent.
2 parents 881c6c4 + e7a1f7b commit dfff8f6

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

compiler/src/dotty/tools/dotc/reporting/Reporter.scala

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import java.io.{BufferedReader, PrintWriter}
1515
import scala.annotation.internal.sharable
1616
import scala.collection.mutable
1717
import core.Decorators.em
18+
import core.handleRecursive
1819

1920
object Reporter {
2021
/** Convert a SimpleReporter into a real Reporter */
@@ -155,6 +156,12 @@ abstract class Reporter extends interfaces.ReporterResult {
155156
addUnreported(key, 1)
156157
case _ =>
157158
if !isHidden(dia) then // avoid isHidden test for summarized warnings so that message is not forced
159+
try
160+
withMode(Mode.Printing)(doReport(dia))
161+
catch case ex: Throwable =>
162+
// #20158: Don't increment the error count, otherwise we might suppress
163+
// the RecursiveOverflow error and not print any error at all.
164+
handleRecursive("error reporting", dia.message, ex)
158165
dia match {
159166
case w: Warning =>
160167
warnings = w :: warnings
@@ -168,7 +175,6 @@ abstract class Reporter extends interfaces.ReporterResult {
168175
// match error if d is something else
169176
}
170177
markReported(dia)
171-
withMode(Mode.Printing)(doReport(dia))
172178
end issueUnconfigured
173179

174180
def issueIfNotSuppressed(dia: Diagnostic)(using Context): Unit =

compiler/test/dotty/tools/dotc/reporting/TestReporter.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with M
7171
}
7272

7373
if dia.level >= WARNING then
74-
_diagnosticBuf.append(dia)
7574
_consoleReporter.doReport(dia)
75+
_diagnosticBuf.append(dia)
7676
printMessageAndPos(dia, extra)
7777
}
7878
}

tests/neg/mt-deskolemize.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait Expr:
2+
type Value
3+
object Expr:
4+
type Of[V] = Expr { type Value = V }
5+
type ExtractValue[F <: Expr] = F match
6+
case Expr.Of[v] => v
7+
import Expr.ExtractValue
8+
9+
class SimpleLoop1 extends Expr:
10+
type Value = ExtractValue[SimpleLoop2]
11+
12+
class SimpleLoop2 extends Expr:
13+
type Value = ExtractValue[SimpleLoop1]
14+
15+
object Test1:
16+
val x: ExtractValue[SimpleLoop1] = 1 // error

0 commit comments

Comments
 (0)