Skip to content

Commit

Permalink
Merge pull request #15037 from dotty-staging/exp-i14907
Browse files Browse the repository at this point in the history
Relax assertion in TyperState#commit If there's nothing to commit; clear unreported warnings in Reporter#flush
  • Loading branch information
odersky committed May 2, 2022
2 parents cad8db8 + 87c97e7 commit 0e83a80
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
19 changes: 11 additions & 8 deletions compiler/src/dotty/tools/dotc/core/TyperState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,21 @@ class TyperState() {
Stats.record("typerState.commit")
assert(isCommittable, s"$this is not committable")
assert(!isCommitted, s"$this is already committed")
reporter.flush()
setCommittable(false)
val targetState = ctx.typerState

// Committing into an already committed TyperState usually doesn't make
// sense since it means the constraints we're committing won't be propagated
// further, but it can happen if the targetState gets captured in a reported
// Message, because forcing that Message might involve creating and
// committing new TyperStates into the captured one after its been committed.
assert(!targetState.isCommitted || targetState.reporter.hasErrors || targetState.reporter.hasWarnings,
val nothingToCommit = (constraint eq targetState.constraint) && !reporter.hasUnreportedMessages
assert(!targetState.isCommitted || nothingToCommit ||
// Committing into an already committed TyperState usually doesn't make
// sense since it means the constraints and messages we're committing won't be propagated
// further, but it can happen if the targetState gets captured in a reported
// Message, because forcing that Message might involve creating and
// committing new TyperStates into the captured one after it's been committed.
targetState.reporter.hasErrors || targetState.reporter.hasWarnings,
s"Attempt to commit $this into already committed $targetState")

reporter.flush()
setCommittable(false)

if constraint ne targetState.constraint then
Stats.record("typerState.commit.new constraint")
constr.println(i"committing $this to $targetState, fromConstr = $constraint, toConstr = ${targetState.constraint}")
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,23 @@ abstract class Reporter extends interfaces.ReporterResult {
*/
def hasUnreportedErrors: Boolean = false

/** Does this reporter contain any message that have yet to be reported by its outer reporter ?
* This includes any warning stored in `unreportedWarnings` which need to be propagated to
* get an accurate count of unreported warnings in the outer reporter.
*/
def hasUnreportedMessages(using Context): Boolean =
pendingMessages.nonEmpty || unreportedWarnings.nonEmpty

/** If this reporter buffers messages, remove and return all buffered messages. */
def removeBufferedMessages(using Context): List[Diagnostic] = Nil

/** Issue all error messages in this reporter to next outer one, or make sure they are written. */
/** Issue all messages in this reporter to next outer one, or make sure they are written. */
def flush()(using Context): Unit =
val msgs = removeBufferedMessages
if msgs.nonEmpty then msgs.foreach(ctx.reporter.report)
for (key, count) <- unreportedWarnings do
ctx.reporter.addUnreported(key, count)
unreportedWarnings = Map.empty

/** If this reporter buffers messages, all buffered messages, otherwise Nil */
def pendingMessages(using Context): List[Diagnostic] = Nil
Expand Down
11 changes: 11 additions & 0 deletions tests/pos/i14907.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
object Module {
class Fun[N <: Int]()
type Fill[N <: Int] = N match {
case 0 => EmptyTuple
case 1 => Any *: Fill[0]
}
extension[N <: Int] (f: Fun[N])
def apply: Fill[N] => Any = ???

Fun[1]()(???)
}

0 comments on commit 0e83a80

Please sign in to comment.