Skip to content

Commit 95f0d5d

Browse files
committed
Fix messages leaking via suspended messages
It isn't clear what StoreReporter's purpose is. Is it simply a store of all messages, or is it a store of "real" messages, i.e. messages that aren't suppressed with `@nowarn` or -Wconf (i.e. configurable warnings)? I believe StoreReporter is often used as a way to get programmatic access to the real messages. Typer, with its TyperState, uses StoreReporter as a more general buffer while making typing attempts, such as when trying to apply an implicit conversion. But with configurable warnings, we don't know if a warning is real or not until we've typed all the `@nowarn` annotation in the code, which is why we suspend the messages, on Run. So we add an override for TyperState, so that StoreReporter is used as simply a buffer. When it then unbuffers its messages in flush to the parent context's reporter, it will run through the regular "issueIfNotSuppressed" code (assuming it's not another store reporter).
1 parent 483bf2c commit 95f0d5d

File tree

4 files changed

+11
-4
lines changed

4 files changed

+11
-4
lines changed

compiler/src/dotty/tools/dotc/core/TyperState.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class TyperState() {
103103
this
104104

105105
/** A fresh typer state with the same constraint as this one. */
106-
def fresh(reporter: Reporter = StoreReporter(this.reporter),
106+
def fresh(reporter: Reporter = StoreReporter(this.reporter, fromTyperState = true),
107107
committable: Boolean = this.isCommittable): TyperState =
108108
util.Stats.record("TyperState.fresh")
109109
TyperState().init(this, this.constraint)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import core.Contexts.Context
77
import Diagnostic._
88

99
/** A re-usable Reporter used in Contexts#test */
10-
class ExploringReporter extends StoreReporter(null):
10+
class ExploringReporter extends StoreReporter(null, fromTyperState = false):
1111
infos = new mutable.ListBuffer[Diagnostic]
1212

1313
override def hasUnreportedErrors: Boolean =

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Diagnostic._
1717
* - The reporter is not flushed and the message containers capture a
1818
* `Context` (about 4MB)
1919
*/
20-
class StoreReporter(outer: Reporter = Reporter.NoReporter) extends Reporter {
20+
class StoreReporter(outer: Reporter = Reporter.NoReporter, fromTyperState: Boolean = false) extends Reporter {
2121

2222
protected var infos: mutable.ListBuffer[Diagnostic] = null
2323

@@ -40,4 +40,11 @@ class StoreReporter(outer: Reporter = Reporter.NoReporter) extends Reporter {
4040
override def pendingMessages(using Context): List[Diagnostic] = if (infos != null) infos.toList else Nil
4141

4242
override def errorsReported: Boolean = hasErrors || (outer != null && outer.errorsReported)
43+
44+
// If this is a TyperState buffering reporter then buffer the messages,
45+
// so that then only when the messages are unbuffered (when the reporter if flushed)
46+
// do they go through -Wconf, and possibly then buffered on the Run as a suspended message
47+
override def report(dia: Diagnostic)(using Context): Unit =
48+
if fromTyperState then doReport(dia)
49+
else super.report(dia)
4350
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import collection.mutable
66
import Diagnostic._
77

88
/** A re-usable Reporter used in Contexts#test */
9-
class TestingReporter extends StoreReporter(null):
9+
class TestingReporter extends StoreReporter(null, fromTyperState = false):
1010
infos = new mutable.ListBuffer[Diagnostic]
1111
override def hasUnreportedErrors: Boolean = infos.exists(_.isInstanceOf[Error])
1212
def reset(): Unit = infos.clear()

0 commit comments

Comments
 (0)