Skip to content

Automatic Type Derivation causes Assertion Error for Non-Static Enum #11174

Closed
@deusaquilus

Description

@deusaquilus

Minimized code

First, let's implement a really simple type derivation that just prints something for every given type in a product/coproduct

object EnumerateNames {

  inline def summonNext[T] =
    summonFrom {
      case en: EnumerateNames[T] => en
    }

  inline def walkThrough[Types <: Tuple]: List[String] =
    inline erasedValue[Types] match
      case _: (tpe *: tpes) =>
        summonNext[tpe].apply +: walkThrough[tpes]
      case _: EmptyTuple =>
        Nil
      

  inline def derived[T]: EnumerateNames[T] = 
    summonFrom {
      case ev: Mirror.Of[T] =>
        new EnumerateNames[T] {
          def apply =
            inline ev match
              case m: Mirror.ProductOf[T] => walkThrough[m.MirroredElemTypes].mkString(", ")
              case m: Mirror.SumOf[T] => walkThrough[m.MirroredElemTypes].mkString(", ")
        }
    }
}

trait EnumerateNames[T] {
  def apply: String
}

Then let's create a class that defines an enum and an automatic derivation for types:

class MainClass {
  enum Shape:
    case Square(width: Int, height: Int) extends Shape
    case Circle(radius: Int) extends Shape

  given EnumerateNames[Int] with {
    def apply: String = "int"
  }
  inline given auto[T]:EnumerateNames[T] = EnumerateNames.derived
  def deriveEnumerateNames[T](using en: EnumerateNames[T]) = en.apply  
  def run: Unit = println( deriveEnumerateNames[Shape] )
}

Then let's call that class:

object Main {
  def main(args: Array[String]) = {
    new MainClass().run
  }
} 

Output

A very large error happens:

exception while typing MainClass.this.Shape$.this of class class dotty.tools.dotc.ast.Trees$This # -1
exception while typing MainClass.this.Shape$.this.Square of class class dotty.tools.dotc.ast.Trees$Select # -1
exception while typing MainClass.this.Shape$.this.Square:
  
    (
      deriving.Mirror{
        MirroredType = io.getquill.MainClass.Shape.Square; 
          MirroredMonoType = io.getquill.MainClass.Shape.Square
        ; MirroredElemTypes <: Tuple
      }
     & 
      scala.deriving.Mirror.Product{
        MirroredMonoType = io.getquill.MainClass.Shape.Square; 
          MirroredType = io.getquill.MainClass.Shape.Square
        ; MirroredLabel = ("Square" : String)
      }
    ){
...
java.lang.AssertionError: assertion failed: failure to construct path from value ev/value elem$1/method apply/anonymous class Object with io.getquill.EnumerateNames {...}/method run/class MainClass/package io.getquill/package io/package <root> to `this` of object Shape in class MainClass;
class MainClass in package io.getquill does not have an outer accessor while compiling /Users/aleiof/git/enum_summon/src/main/scala/io/getquill/Example.scala, /Users/aleiof/git/enum_summon/src/main/scala/io/getquill/Main.scala
[error] ## Exception when compiling 2 sources to /Users/aleiof/git/enum_summon/target/scala-3.0.0-M3/classes
[error] java.lang.AssertionError: assertion failed: failure to construct path from value ev/value elem$1/method apply/anonymous class Object with io.getquill.EnumerateNames {...}/method run/class MainClass/package io.getquill/package io/package <root> to `this` of object Shape in class MainClass;
[error] class MainClass in package io.getquill does not have an outer accessor
[error] scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[error] dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.loop$1(ExplicitOuter.scala:410
[error] dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.path$extension(ExplicitOuter.scala:429)
[error] dotty.tools.dotc.transform.Erasure$Typer.typedThis(Erasure.scala:750)
[error] dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2529)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2590)
[error] dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:118)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2659)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2663)
[error] dotty.tools.dotc.transform.Erasure$Typer.typedSelect(Erasure.scala:641)
[error] dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2498)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2589)
[error] dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:118)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2659)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2663)
[error] dotty.tools.dotc.transform.Erasure$Typer.typedTyped(Erasure.scala:603)
[error] dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2533)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2590)
[error] dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:118)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2659)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2663)
[error] dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:2779)
[error] dotty.tools.dotc.transform.Erasure$Typer.typedTypeApply(Erasure.scala:767)
[error] dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2547)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2590)
[error] dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:118)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2659)
...
[error] (Compile / compileIncremental) java.lang.AssertionError: assertion failed: failure to construct path from value ev/value elem$1/method apply/anonymous class Object with io.getquill.EnumerateNames {...}/method run/class MainClass/package io.getquill/package io/package <root> to `this` of object Shape in class MainClass;
[error] class MainClass in package io.getquill does not have an outer accessor
[error] Total time: 1 s, completed Jan 20, 2021 2:24:19 AM

Expectation

Compilation should work and "int, int, int" should be returned.

Workaround

Moving the enum to a static place (e.g. into an object) seems to solve the problem.

Repo

Repository with code sample can be found here:
https://github.com/deusaquilus/enum_summon

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions