From 202b9674aa8041af8ecb59b247ded01ad7bf536b Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 6 Apr 2018 01:56:06 +0200 Subject: [PATCH] Fix reporter reuse in TyperState#test The previous logic was wrong: TyperState#test may be called by the closure passed to TyperState#test, meaning that the testReporter may already be in use at that point. --- .../dotty/tools/dotc/core/TyperState.scala | 19 ++++++++++++++++--- .../tools/dotc/reporting/StoreReporter.scala | 4 +--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala index f54e6af62b4e..10378131be63 100644 --- a/compiler/src/dotty/tools/dotc/core/TyperState.scala +++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala @@ -100,7 +100,7 @@ class TyperState(previous: TyperState /* | Null */) { def uncommittedAncestor: TyperState = if (isCommitted) previous.uncommittedAncestor else this - private[this] var testReporter: StoreReporter = null + private[this] var testReporter: TestReporter = null /** Test using `op`. If current typerstate is shared, run `op` in a fresh exploration * typerstate. If it is unshared, run `op` in current typerState, restoring typerState @@ -116,15 +116,17 @@ class TyperState(previous: TyperState /* | Null */) { val savedCommitted = isCommitted myIsCommittable = false myReporter = { - if (testReporter == null) { - testReporter = new StoreReporter(reporter) + if (testReporter == null || testReporter.inUse) { + testReporter = new TestReporter(reporter) } else { testReporter.reset() } + testReporter.inUse = true testReporter } try op(ctx) finally { + testReporter.inUse = false resetConstraintTo(savedConstraint) myReporter = savedReporter myIsCommittable = savedCommittable @@ -189,3 +191,14 @@ class TyperState(previous: TyperState /* | Null */) { def stateChainStr: String = s"$this${if (previous == null) "" else previous.stateChainStr}" } + +/** Temporary, reusable reporter used in TyperState#test */ +private class TestReporter(outer: Reporter) extends StoreReporter(outer) { + /** Is this reporter currently used in a test? */ + var inUse = false + + def reset() = { + assert(!inUse, s"Cannot reset reporter currently in use: $this") + infos = null + } +} diff --git a/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala b/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala index acb0d573507d..243a4cca0130 100644 --- a/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala @@ -20,9 +20,7 @@ import diagnostic.messages._ */ class StoreReporter(outer: Reporter) extends Reporter { - private[this] var infos: mutable.ListBuffer[MessageContainer] = null - - def reset() = infos = null + protected[this] var infos: mutable.ListBuffer[MessageContainer] = null def doReport(m: MessageContainer)(implicit ctx: Context): Unit = { typr.println(s">>>> StoredError: ${m.message}") // !!! DEBUG