diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala index 9aa51a6714c3..6163eebfbef4 100644 --- a/compiler/src/dotty/tools/dotc/core/TyperState.scala +++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala @@ -103,7 +103,7 @@ class TyperState() { this /** A fresh typer state with the same constraint as this one. */ - def fresh(reporter: Reporter = StoreReporter(this.reporter), + def fresh(reporter: Reporter = StoreReporter(this.reporter, fromTyperState = true), committable: Boolean = this.isCommittable): TyperState = util.Stats.record("TyperState.fresh") TyperState().init(this, this.constraint) diff --git a/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala b/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala index e7b636cddf02..9255820140d8 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala @@ -7,7 +7,7 @@ import core.Contexts.Context import Diagnostic._ /** A re-usable Reporter used in Contexts#test */ -class ExploringReporter extends StoreReporter(null): +class ExploringReporter extends StoreReporter(null, fromTyperState = false): infos = new mutable.ListBuffer[Diagnostic] override def hasUnreportedErrors: Boolean = diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index 8c736993de8e..e159b5f83863 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -137,42 +137,44 @@ abstract class Reporter extends interfaces.ReporterResult { var unreportedWarnings: Map[String, Int] = Map.empty + /** Issue the diagnostic, ignoring `-Wconf` and `@nowarn` configurations, + * but still honouring `-nowarn`, `-Werror`, and conditional warnings. */ + def issueUnconfigured(dia: Diagnostic)(using Context): Unit = dia match + case w: Warning if ctx.settings.silentWarnings.value => + case w: ConditionalWarning if w.isSummarizedConditional => + val key = w.enablingOption.name + val count = unreportedWarnings.getOrElse(key, 0) + unreportedWarnings = unreportedWarnings.updated(key, count + 1) + case _ => + // conditional warnings that are not enabled are not fatal + val d = dia match + case w: Warning if ctx.settings.XfatalWarnings.value => w.toError + case _ => dia + if !isHidden(d) then // avoid isHidden test for summarized warnings so that message is not forced + withMode(Mode.Printing)(doReport(d)) + d match { + case _: Warning => _warningCount += 1 + case e: Error => + errors = e :: errors + _errorCount += 1 + if ctx.typerState.isGlobalCommittable then + ctx.base.errorsToBeReported = true + case _: Info => // nothing to do here + // match error if d is something else + } + end issueUnconfigured + def issueIfNotSuppressed(dia: Diagnostic)(using Context): Unit = def go() = import Action._ - - val toReport = dia match - case w: Warning => - def fatal(w: Warning) = if ctx.settings.XfatalWarnings.value && !w.isSummarizedConditional then Some(w.toError) else Some(w) - if ctx.settings.silentWarnings.value then None - else WConf.parsed.action(dia) match - case Silent => None - case Info => Some(w.toInfo) - case Warning => fatal(w) - case Verbose => fatal(w).tap(_.foreach(_.setVerbose())) - case Error => Some(w.toError) - case _ => Some(dia) - - toReport foreach { - case cw: ConditionalWarning if cw.isSummarizedConditional => - val key = cw.enablingOption.name - unreportedWarnings = - unreportedWarnings.updated(key, unreportedWarnings.getOrElse(key, 0) + 1) - case d if !isHidden(d) => - withMode(Mode.Printing)(doReport(d)) - d match { - case _: Warning => _warningCount += 1 - case e: Error => - errors = e :: errors - _errorCount += 1 - if ctx.typerState.isGlobalCommittable then - ctx.base.errorsToBeReported = true - case _: Info => // nothing to do here - // match error if d is something else - } - case _ => // hidden - } - end go + dia match + case w: Warning => WConf.parsed.action(w) match + case Error => issueUnconfigured(w.toError) + case Warning => issueUnconfigured(w) + case Verbose => issueUnconfigured(w.setVerbose()) + case Info => issueUnconfigured(w.toInfo) + case Silent => + case _ => issueUnconfigured(dia) // `ctx.run` can be null in test, also in the repl when parsing the first line. The parser runs early, the Run is // only created in ReplDriver.compile when a line is submitted. This means that `@nowarn` doesnt work on parser diff --git a/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala b/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala index d3c334599666..db39ed6527d1 100644 --- a/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala @@ -17,7 +17,7 @@ import Diagnostic._ * - The reporter is not flushed and the message containers capture a * `Context` (about 4MB) */ -class StoreReporter(outer: Reporter = Reporter.NoReporter) extends Reporter { +class StoreReporter(outer: Reporter = Reporter.NoReporter, fromTyperState: Boolean = false) extends Reporter { protected var infos: mutable.ListBuffer[Diagnostic] = null @@ -40,4 +40,11 @@ class StoreReporter(outer: Reporter = Reporter.NoReporter) extends Reporter { override def pendingMessages(using Context): List[Diagnostic] = if (infos != null) infos.toList else Nil override def errorsReported: Boolean = hasErrors || (outer != null && outer.errorsReported) + + // If this is a TyperState buffering reporter then buffer the messages, + // so that then only when the messages are unbuffered (when the reporter if flushed) + // do they go through -Wconf, and possibly then buffered on the Run as a suspended message + override def report(dia: Diagnostic)(using Context): Unit = + if fromTyperState then issueUnconfigured(dia) + else super.report(dia) } diff --git a/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala b/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala index 8ad5b525de5c..a3d84e462bf0 100644 --- a/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala @@ -6,7 +6,7 @@ import collection.mutable import Diagnostic._ /** A re-usable Reporter used in Contexts#test */ -class TestingReporter extends StoreReporter(null): +class TestingReporter extends StoreReporter(null, fromTyperState = false): infos = new mutable.ListBuffer[Diagnostic] override def hasUnreportedErrors: Boolean = infos.exists(_.isInstanceOf[Error]) def reset(): Unit = infos.clear()