Skip to content

Commit

Permalink
Avoid crash by relaxing TyperState assertion
Browse files Browse the repository at this point in the history
Flushing a reporter might force error messages (in particular when a
StoreReporter is flushed into a non-StoreReporter), and the TyperState
of the context captured in an error message might already be committed
at this point. In ea6449f I tried to
deal with this by flushing before committing but that's not sufficient
since the reporter we're flushing might contain error messages from a
more deeply nested TyperState. So this commit just relaxes the assertion
(ideally we would also check that only TyperStates created in a
committed TyperState can be committed in one, but keeping track of that
would require an extra field in TyperState).
  • Loading branch information
smarter committed Jul 25, 2021
1 parent ec15557 commit 7366440
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TyperState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class TyperState() {
reporter.flush()
setCommittable(false)
val targetState = ctx.typerState
assert(!targetState.isCommitted, s"Attempt to commit $this into already committed $targetState")
assert(!targetState.isCommitted || ctx.reporter.errorsReported, s"Attempt to commit $this into already committed $targetState")
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
24 changes: 24 additions & 0 deletions tests/neg/i13101.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
trait Vehicle
trait Car extends Vehicle

trait Encoder[A]
object Encoder {
implicit val encodeVehicle: Encoder[Vehicle] = ???
implicit val encodeCar: Encoder[Car] = ???
}

trait Route
trait Printer
trait Marshaller[-A] // must be contravariant

object Test {
implicit def marshaller[A: Encoder](implicit p: Printer = ???): Marshaller[A] = ???
// the `Printer` implicit arg seems to be necessary, either with default value, or no implicit in scope

def foo[A](v: A)(implicit m: Marshaller[A]): Route = ???

val route: Route = identity {
val f: (Car => Route) => Route = ??? // ok if s/Car/Vehicle/
f(vehicle => foo(vehicle)) // error: ambiguous implicit
}
}

0 comments on commit 7366440

Please sign in to comment.