diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 84ba0a452a2e..6ef1856f5cfa 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -526,6 +526,10 @@ object Contexts { final def withOwner(owner: Symbol): Context = if (owner ne this.owner) fresh.setOwner(owner) else this + final def withUncommittedTyperState: Context = + val ts = typerState.uncommittedAncestor + if ts ne typerState then fresh.setTyperState(ts) else this + final def withProperty[T](key: Key[T], value: Option[T]): Context = if (property(key) == value) this else value match { diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala index 6fd7f48bc54f..2c41fc8f0231 100644 --- a/compiler/src/dotty/tools/dotc/core/TyperState.scala +++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala @@ -138,9 +138,12 @@ class TyperState() { */ def commit()(using Context): Unit = { Stats.record("typerState.commit") - assert(isCommittable) + assert(isCommittable, s"$this is not committable") + assert(!isCommitted, s"$this is already committed") + reporter.flush() setCommittable(false) val targetState = ctx.typerState + assert(!targetState.isCommitted, 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}") @@ -150,7 +153,6 @@ class TyperState() { else targetState.mergeConstraintWith(this) targetState.gc() - reporter.flush() isCommitted = true } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index eff4a8cb9c94..8a4de6ec13e2 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -388,8 +388,8 @@ object ProtoTypes { if state.typedArgs.size == args.length then state.typedArgs else val passedTyperState = ctx.typerState - inContext(protoCtx) { - val protoTyperState = protoCtx.typerState + inContext(protoCtx.withUncommittedTyperState) { + val protoTyperState = ctx.typerState val oldConstraint = protoTyperState.constraint val args1 = args.mapWithIndexConserve((arg, idx) => cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false)) diff --git a/tests/neg/i12736a.scala b/tests/neg/i12736a.scala new file mode 100644 index 000000000000..509465ea3f07 --- /dev/null +++ b/tests/neg/i12736a.scala @@ -0,0 +1,6 @@ +object Test { + def apply[S](r: Any): Any = r + + def test = + (x: Int) => Test(doesntexist, x) // error +} diff --git a/tests/neg/i12736b.scala b/tests/neg/i12736b.scala new file mode 100644 index 000000000000..c7db2f7a92ea --- /dev/null +++ b/tests/neg/i12736b.scala @@ -0,0 +1,6 @@ +object Test { + def apply[S](r: Any)(using DoesntExist): Any = r // error + + def test(o: Option[Any]) = + o.map(x => Test(doesntExist, x)) // error +}