Skip to content

Commit 7366440

Browse files
committed
Avoid crash by relaxing TyperState assertion
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).
1 parent ec15557 commit 7366440

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

compiler/src/dotty/tools/dotc/core/TyperState.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class TyperState() {
143143
reporter.flush()
144144
setCommittable(false)
145145
val targetState = ctx.typerState
146-
assert(!targetState.isCommitted, s"Attempt to commit $this into already committed $targetState")
146+
assert(!targetState.isCommitted || ctx.reporter.errorsReported, s"Attempt to commit $this into already committed $targetState")
147147
if constraint ne targetState.constraint then
148148
Stats.record("typerState.commit.new constraint")
149149
constr.println(i"committing $this to $targetState, fromConstr = $constraint, toConstr = ${targetState.constraint}")

tests/neg/i13101.scala

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
trait Vehicle
2+
trait Car extends Vehicle
3+
4+
trait Encoder[A]
5+
object Encoder {
6+
implicit val encodeVehicle: Encoder[Vehicle] = ???
7+
implicit val encodeCar: Encoder[Car] = ???
8+
}
9+
10+
trait Route
11+
trait Printer
12+
trait Marshaller[-A] // must be contravariant
13+
14+
object Test {
15+
implicit def marshaller[A: Encoder](implicit p: Printer = ???): Marshaller[A] = ???
16+
// the `Printer` implicit arg seems to be necessary, either with default value, or no implicit in scope
17+
18+
def foo[A](v: A)(implicit m: Marshaller[A]): Route = ???
19+
20+
val route: Route = identity {
21+
val f: (Car => Route) => Route = ??? // ok if s/Car/Vehicle/
22+
f(vehicle => foo(vehicle)) // error: ambiguous implicit
23+
}
24+
}

0 commit comments

Comments
 (0)