scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

Assertion failed "class defined twice" with testCompilation

Open aherlihy opened this issue 1 year ago • 3 comments

Compiler version

3.4.2-RC1

Minimized code

$sbt testCompilation tests/pos/shared-classname.scala. Does not fail with scalac tests/pos/shared-classname.scala.

(shortened version of not-looping-implicit.scala with the anonymous classes given the same name).

import scala.deriving.Mirror
import scala.compiletime._
trait Schema[T]
object Schema {
  inline given derived[A]: Schema[A] =
    inline summonInline[Mirror.Of[A]] match {
      case m: Mirror.SumOf[A] =>
        summonInline[Schema[m.MirroredElemTypes]]
        class InlinedSchema extends Schema[A] {}
        new InlinedSchema
      case m: Mirror.ProductOf[A] =>
        class InlinedSchema extends Schema[A] {}
        new InlinedSchema
    }
}
sealed trait InputValue
object InputValue {
  case class T() extends InputValue
}
@main def Test:Schema[InputValue] =
  Schema.derived

Output (click arrow to expand)

completed (0/1, 0 failed, 0s)java.lang.AssertionError: assertion failed: class defined twice class Schema$_$InlinedSchema 7130 6099
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.transform.TreeChecker.testDuplicate(TreeChecker.scala:55)
        ...

aherlihy avatar Apr 30 '24 08:04 aherlihy

Fails Ycheck after genSJSIR

checking t/Test.scala after phase MegaPhase{dropOuterAccessors, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}
checking t/Test.scala after phase genSJSIR
java.lang.AssertionError: assertion failed: class defined twice class Schema$_$InlinedSchema 6090 7121
        at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
        at dotty.tools.dotc.transform.TreeChecker.testDuplicate(TreeChecker.scala:55)
        at dotty.tools.dotc.transform.TreeChecker.transformSym(TreeChecker.scala:78)
        at dotty.tools.dotc.core.DenotTransformers$SymTransformer.transform(DenotTransformers.scala:72)

nicolasstucki avatar Apr 30 '24 09:04 nicolasstucki

Minimization

trait Foo

object Foo {
  inline def bar(): Foo =
    class InlinedFoo extends Foo {}
    new InlinedFoo

  inline def foo(): Foo =
    bar()
    class InlinedFoo extends Foo {}
    new InlinedFoo

  def Test: Foo = Foo.foo()
}

nicolasstucki avatar Apr 30 '24 09:04 nicolasstucki

@sjrd could you check if this is an issue with genSJSIR or before that pahse?

nicolasstucki avatar Apr 30 '24 09:04 nicolasstucki

Something really weird is happening here. genSJSIR doesn't actually do anything, since -scalajs is not activated. However, its mere presence means that Ycheck gets to run twice between flatten and genBCode. It is the fact that Ycheck runs twice that somehow causes this class to be transformed twice, resulting in duplicates.

Moreover, -Ycheck:flatten alone does not cause the issue. -Ycheck:genSJSIR alone does not cause the issue. But the combined -Ycheck:flatten,genSJSIR does cause the issue!

Does that mean there's something side-effecting about Ycheck itself? Or that a previous transform side-effects while transforming symbols? It's all very strange, but in any case it's not about genSJSIR per se. We could replace it with a completely empty phase and the same issue would appear.

sjrd avatar Jun 26 '24 11:06 sjrd