diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index c6bb37ff9a85..42ec0ee1c857 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -929,6 +929,17 @@ object Contexts { /** Flag to suppress inlining, set after overflow */ private[dotc] var stopInlining: Boolean = false + /** A variable that records that some error was reported in a globally committable context. + * The error will not necessarlily be emitted, since it could still be that + * the enclosing context will be aborted. The variable is used as a smoke test + * to turn off assertions that might be wrong if the program is erroneous. To + * just test for `ctx.reporter.errorsReported` is not always enough, since it + * could be that the context in which the assertion is tested is a completer context + * that's different from the context where the error was reported. See i13218.scala + * for a test. + */ + private[dotc] var errorsToBeReported = false + // Reporters state private[dotc] var indent: Int = 0 @@ -958,6 +969,7 @@ object Contexts { uniqueNamedTypes.clear() emptyTypeBounds = null emptyWildcardBounds = null + errorsToBeReported = false errorTypeMsg.clear() sources.clear() files.clear() diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index 437963af9161..64a2d826075e 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -157,6 +157,8 @@ abstract class Reporter extends interfaces.ReporterResult { case dia: Error => errors = dia :: errors _errorCount += 1 + if ctx.typerState.isGlobalCommittable then + ctx.base.errorsToBeReported = true case dia: Info => // nothing to do here // match error if d is something else diff --git a/compiler/src/dotty/tools/dotc/util/Attachment.scala b/compiler/src/dotty/tools/dotc/util/Attachment.scala index 582ff6da0557..8f0e5dd97dfe 100644 --- a/compiler/src/dotty/tools/dotc/util/Attachment.scala +++ b/compiler/src/dotty/tools/dotc/util/Attachment.scala @@ -117,7 +117,7 @@ object Attachment { } final def pushAttachment[V](key: Key[V], value: V)(using ctx: Context): Unit = { - assert(!hasAttachment(key) || ctx.reporter.errorsReported, s"duplicate attachment for key $key") + assert(!hasAttachment(key) || ctx.base.errorsToBeReported, s"duplicate attachment for key $key") next = new Link(key, value, next) } diff --git a/tests/neg/i13218.scala b/tests/neg/i13218.scala new file mode 100644 index 000000000000..e033a3637461 --- /dev/null +++ b/tests/neg/i13218.scala @@ -0,0 +1,14 @@ +class TagTest extends AnyFreeSpec: + "a" - { + "b" in { + class TF[F[_]] + meow // error + } + } + +trait AnyFreeSpec: + protected class Wrapper(s: String): + def -(f: => Unit): Unit = ??? + def in(f: => Unit): Unit = ??? + + implicit def wrap(s: String): Wrapper = ???