Skip to content

Assertion failure in TypeErasure#sigName: "no sig for MethodType" #15649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
griggt opened this issue Jul 11, 2022 · 5 comments · Fixed by #15658
Closed

Assertion failure in TypeErasure#sigName: "no sig for MethodType" #15649

griggt opened this issue Jul 11, 2022 · 5 comments · Fixed by #15658
Assignees
Labels
area:erasure itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Milestone

Comments

@griggt
Copy link
Contributor

griggt commented Jul 11, 2022

Minimized from the community-build failure of zio/zio-config reported in #15647

Compiler version

3.2.0-RC2
Works on 3.1.3
Fails on 3.2.0-RC1
Fails on 3.2.1-RC1-bin-20220710-794e7c9-NIGHTLY

Minimized code

trait ConfigSourceModule:
  object ConfigSource:
    class R

object M extends ConfigSourceModule

object Foo:
  implicit class FromConfigSource(c: M.ConfigSource.type)

object FooBar:                                      // problem disappears if we rename as `Bar`
  def foo: M.ConfigSource.R = new M.ConfigSource.R  // problem disappears if we use `???` as rhs

Output (click arrow to expand)

java.lang.AssertionError: assertion failed: MethodType(List(), List(), TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),trait ConfigSourceModule)),module class ConfigSource$))
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.TypeErasure.dotty$tools$dotc$core$TypeErasure$$sigName(TypeErasure.scala:851)
	at dotty.tools.dotc.core.TypeErasure$.sigName(TypeErasure.scala:204)
	at dotty.tools.dotc.core.Signature.$anonfun$2(Signature.scala:111)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Signature.prependTermParams(Signature.scala:111)
	at dotty.tools.dotc.core.Types$MethodOrPoly.computeSignature$2(Types.scala:3560)
	at dotty.tools.dotc.core.Types$MethodOrPoly.signature(Types.scala:3577)
	at dotty.tools.dotc.core.Types$MethodOrPoly.signature(Types.scala:3587)
	at dotty.tools.dotc.core.TypeComparer.compareMethod$1(TypeComparer.scala:703)
	at dotty.tools.dotc.core.TypeComparer.thirdTry$1(TypeComparer.scala:709)
	at dotty.tools.dotc.core.TypeComparer.secondTry$1(TypeComparer.scala:506)
	at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:383)
	at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1336)
	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:194)
	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:204)
	at dotty.tools.dotc.core.TypeComparer.isSameType(TypeComparer.scala:2019)
	at dotty.tools.dotc.core.TypeComparer$.isSameType(TypeComparer.scala:2761)
	at dotty.tools.dotc.core.Types$Type.$eq$colon$eq(Types.scala:1056)
	at dotty.tools.backend.jvm.BCodeHelpers.dotty$tools$backend$jvm$BCodeHelpers$$getStaticForwarderGenericSignature(BCodeHelpers.scala:920)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarder(BCodeHelpers.scala:514)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarders$$anonfun$3(BCodeHelpers.scala:594)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarders(BCodeHelpers.scala:596)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarders$(BCodeHelpers.scala:490)
	at dotty.tools.backend.jvm.BCodeHelpers$JCommonBuilder.addForwarders(BCodeHelpers.scala:654)
	at dotty.tools.backend.jvm.BCodeHelpers$JMirrorBuilder.genMirrorClass(BCodeHelpers.scala:701)
	at dotty.tools.backend.jvm.GenBCodePipeline$Worker1.visit(GenBCode.scala:257)
	at dotty.tools.backend.jvm.GenBCodePipeline$Worker1.run(GenBCode.scala:231)
	at dotty.tools.backend.jvm.GenBCodePipeline.buildAndSendToDisk(GenBCode.scala:598)
	at dotty.tools.backend.jvm.GenBCodePipeline.run(GenBCode.scala:564)
	at dotty.tools.backend.jvm.GenBCode.run(GenBCode.scala:69)
	at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:311)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:312)
	at dotty.tools.backend.jvm.GenBCode.runOn(GenBCode.scala:77)
	at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:234)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1328)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:245)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:253)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:262)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:262)
	at dotty.tools.dotc.Run.compileSources(Run.scala:186)
	at dotty.tools.dotc.Run.compile(Run.scala:170)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:35)
	at dotty.tools.dotc.Driver.process(Driver.scala:195)
	at dotty.tools.dotc.Driver.process(Driver.scala:163)
	at dotty.tools.dotc.Driver.process(Driver.scala:175)
	at dotty.tools.dotc.Driver.main(Driver.scala:205)
	at dotty.tools.dotc.Main.main(Main.scala)
no sig for MethodType(List(), List(), TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),trait ConfigSourceModule)),module class ConfigSource$)) because of ()
assertion failure for (c(): ConfigSourceModule.this.ConfigSource): Foo.FromConfigSource <:< (c: ConfigSourceModule.this.ConfigSource): Foo.FromConfigSource, frozen = false
Error while emitting ConfigSourceModule.scala
exception occurred while compiling ConfigSourceModule.scala
java.lang.AssertionError: assertion failed: MethodType(List(), List(), TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),trait ConfigSourceModule)),module class ConfigSource$)) while compiling ConfigSourceModule.scala
Exception in thread "main" java.lang.AssertionError: assertion failed: MethodType(List(), List(), TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),trait ConfigSourceModule)),module class ConfigSource$))
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.TypeErasure.dotty$tools$dotc$core$TypeErasure$$sigName(TypeErasure.scala:851)
	at dotty.tools.dotc.core.TypeErasure$.sigName(TypeErasure.scala:204)
	at dotty.tools.dotc.core.Signature.$anonfun$2(Signature.scala:111)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Signature.prependTermParams(Signature.scala:111)
	at dotty.tools.dotc.core.Types$MethodOrPoly.computeSignature$2(Types.scala:3560)
	at dotty.tools.dotc.core.Types$MethodOrPoly.signature(Types.scala:3577)
	at dotty.tools.dotc.core.Types$MethodOrPoly.signature(Types.scala:3587)
	at dotty.tools.dotc.core.TypeComparer.compareMethod$1(TypeComparer.scala:703)
	at dotty.tools.dotc.core.TypeComparer.thirdTry$1(TypeComparer.scala:709)
	at dotty.tools.dotc.core.TypeComparer.secondTry$1(TypeComparer.scala:506)
	at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:383)
	at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1336)
	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:194)
	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:204)
	at dotty.tools.dotc.core.TypeComparer.isSameType(TypeComparer.scala:2019)
	at dotty.tools.dotc.core.TypeComparer$.isSameType(TypeComparer.scala:2761)
	at dotty.tools.dotc.core.Types$Type.$eq$colon$eq(Types.scala:1056)
	at dotty.tools.backend.jvm.BCodeHelpers.dotty$tools$backend$jvm$BCodeHelpers$$getStaticForwarderGenericSignature(BCodeHelpers.scala:920)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarder(BCodeHelpers.scala:514)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarders$$anonfun$3(BCodeHelpers.scala:594)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarders(BCodeHelpers.scala:596)
	at dotty.tools.backend.jvm.BCodeHelpers$BCForwardersGen.addForwarders$(BCodeHelpers.scala:490)
	at dotty.tools.backend.jvm.BCodeHelpers$JCommonBuilder.addForwarders(BCodeHelpers.scala:654)
	at dotty.tools.backend.jvm.BCodeHelpers$JMirrorBuilder.genMirrorClass(BCodeHelpers.scala:701)
	at dotty.tools.backend.jvm.GenBCodePipeline$Worker1.visit(GenBCode.scala:257)
	at dotty.tools.backend.jvm.GenBCodePipeline$Worker1.run(GenBCode.scala:231)
	at dotty.tools.backend.jvm.GenBCodePipeline.buildAndSendToDisk(GenBCode.scala:598)
	at dotty.tools.backend.jvm.GenBCodePipeline.run(GenBCode.scala:564)
	at dotty.tools.backend.jvm.GenBCode.run(GenBCode.scala:69)
	at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:311)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:312)
	at dotty.tools.backend.jvm.GenBCode.runOn(GenBCode.scala:77)
	at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:234)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1328)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:245)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:253)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:262)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:262)
	at dotty.tools.dotc.Run.compileSources(Run.scala:186)
	at dotty.tools.dotc.Run.compile(Run.scala:170)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:35)
	at dotty.tools.dotc.Driver.process(Driver.scala:195)
	at dotty.tools.dotc.Driver.process(Driver.scala:163)
	at dotty.tools.dotc.Driver.process(Driver.scala:175)
	at dotty.tools.dotc.Driver.main(Driver.scala:205)
	at dotty.tools.dotc.Main.main(Main.scala)
@griggt griggt added itype:bug itype:crash regression This worked in a previous version but doesn't anymore stat:needs triage Every issue needs to have an "area" and "itype" label labels Jul 11, 2022
@griggt
Copy link
Contributor Author

griggt commented Jul 11, 2022

It seems as though there may be some non-determinism involved in this failure. While attempting to bisect it, it intermittently stopped reproducing (I've seen this behavior on Scastie as well, here's a run where it failed: https://scastie.scala-lang.org/OvLSO3O5SHCnicilO8PHrg).

@odersky
Copy link
Contributor

odersky commented Jul 12, 2022

I compiled this on main once, compiled OK.
A second compile crashed with a stacktrace like the one shown.

I then cleaned the output directory (which is on my classpath) and compiled another 10 times. Everything compiled OK.

Which makes me think that this is somehow sensitive to some unrelated class file on the class path.

It would be good to find the commit that caused this, even though with the flakey behavior it will be diffcult.

@odersky
Copy link
Contributor

odersky commented Jul 12, 2022

Yes, it looks highly non-deterministic. I could find out that it sees a MethodType that has another MethodType as parameter type, which makes no sense at all. But when I try to add an assertion to find out where it happens I can't make it crash again...

odersky added a commit to dotty-staging/dotty that referenced this issue Jul 12, 2022
If a getter TermRef has a MethodType, erase it to the erasure of the method
result type.

Fixes scala#15649

Since the fault in scala#15649 is highly non-deterministic, I can only guess what the reason
was. I think what happened was that the TermRef was created very late, when the TermRef
was already a getter. I.e. after phase `Getters`, which is itself after `Erasure`. The
whole thing was launched from the code that generates static forwarders in the backend.

Type erasure is run at erasure phase, but if there is no previous denotation of the `TermRef`,
it will keep the first one it read, which would have the `MethodType` as underlying type.
The end result was that the `TermRef` was erased to a method type, where it should have
been erased to the result type. Consequently, we ended up with a MethodType as the
parameter type of another method, which is unexpected.

But all that is just a guess. I am not even sure this PR will fix the problem since it
comes up so rarely.
@mbovel mbovel added area:erasure and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Jul 12, 2022
@griggt
Copy link
Contributor Author

griggt commented Jul 12, 2022

I spent some more time attempting to track this down. Today I used a significantly faster machine (i5-12400 vs. i5-4590s) and older JDK (8 vs. 17). For whatever reason, the behavior seemed more stable and the effort was more productive.

I was able to replicate the crash as early as ae5f986 (the merge commit for #15129), but despite repeated efforts could not get it to crash on the parent merge commit a293d7d.

Diving into the individual commits of that PR, it crashed on e609851 but not a690de2.

So my best guess is the first bad commit is e609851 from #15129.

@smarter
Copy link
Member

smarter commented Jul 12, 2022

So my best guess is the first bad commit is e609851 from #15129.

I did worry about this sort of things at the time: #15129 (comment) :)

Kordyjan pushed a commit to dotty-staging/dotty that referenced this issue Jul 26, 2022
If a getter TermRef has a MethodType, erase it to the erasure of the method
result type.

Fixes scala#15649

Since the fault in scala#15649 is highly non-deterministic, I can only guess what the reason
was. I think what happened was that the TermRef was created very late, when the TermRef
was already a getter. I.e. after phase `Getters`, which is itself after `Erasure`. The
whole thing was launched from the code that generates static forwarders in the backend.

Type erasure is run at erasure phase, but if there is no previous denotation of the `TermRef`,
it will keep the first one it read, which would have the `MethodType` as underlying type.
The end result was that the `TermRef` was erased to a method type, where it should have
been erased to the result type. Consequently, we ended up with a MethodType as the
parameter type of another method, which is unexpected.

But all that is just a guess. I am not even sure this PR will fix the problem since it
comes up so rarely.
Kordyjan pushed a commit to dotty-staging/dotty that referenced this issue Jul 26, 2022
If a getter TermRef has a MethodType, erase it to the erasure of the method
result type.

Fixes scala#15649

Since the fault in scala#15649 is highly non-deterministic, I can only guess what the reason
was. I think what happened was that the TermRef was created very late, when the TermRef
was already a getter. I.e. after phase `Getters`, which is itself after `Erasure`. The
whole thing was launched from the code that generates static forwarders in the backend.

Type erasure is run at erasure phase, but if there is no previous denotation of the `TermRef`,
it will keep the first one it read, which would have the `MethodType` as underlying type.
The end result was that the `TermRef` was erased to a method type, where it should have
been erased to the result type. Consequently, we ended up with a MethodType as the
parameter type of another method, which is unexpected.

But all that is just a guess. I am not even sure this PR will fix the problem since it
comes up so rarely.
bishabosha pushed a commit to dotty-staging/dotty that referenced this issue Oct 18, 2022
If a getter TermRef has a MethodType, erase it to the erasure of the method
result type.

Fixes scala#15649

Since the fault in scala#15649 is highly non-deterministic, I can only guess what the reason
was. I think what happened was that the TermRef was created very late, when the TermRef
was already a getter. I.e. after phase `Getters`, which is itself after `Erasure`. The
whole thing was launched from the code that generates static forwarders in the backend.

Type erasure is run at erasure phase, but if there is no previous denotation of the `TermRef`,
it will keep the first one it read, which would have the `MethodType` as underlying type.
The end result was that the `TermRef` was erased to a method type, where it should have
been erased to the result type. Consequently, we ended up with a MethodType as the
parameter type of another method, which is unexpected.

But all that is just a guess. I am not even sure this PR will fix the problem since it
comes up so rarely.
@Kordyjan Kordyjan added this to the 3.2.1 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:erasure itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants