Skip to content

Type Lambda Crashes Compiler #13460

Closed
@AugustNagro

Description

@AugustNagro

Compiler version

3.0.2

Minimized code

Full runnable example below, but this is the key part:

  private inline def summonElementTypeClasses[A](m: Mirror.Of[A]): IArray[Object] =
    // this doesn't work
    summonAll[Tuple.Map[m.MirroredElemTypes, [A] =>> Lazy[MyTypeClass[A]]]].toIArray
    // but this does
    // summonAll[Tuple.Map[Tuple.Map[m.MirroredElemTypes, MyTypeClass], Lazy]].toIArray

Full reproducer:

https://scastie.scala-lang.org/OI631SqsStStKTxVkwJbjg

import scala.compiletime.*
import scala.deriving.Mirror

class Lazy[A](obj: => A) {
  lazy val value: A = obj
}
object Lazy {
  given [A](using obj: => A ): Lazy[A] = new Lazy(obj) 
}

trait MyTypeClass[A] {
  def makeString(a: A): String
}
object MyTypeClass {
  
  given IntTypeClass: MyTypeClass[Int] with
    def makeString(a: Int): String = a.toString
  
  inline given derived[A](using m: Mirror.Of[A]): MyTypeClass[A] =
    inline m match
      case p: Mirror.ProductOf[A] => productConverter(p)
  
  
  private inline def summonElementTypeClasses[A](m: Mirror.Of[A]): IArray[Object] =
    // this doesn't work
    summonAll[Tuple.Map[m.MirroredElemTypes, [A] =>> Lazy[MyTypeClass[A]]]].toIArray
    // but this does
    // summonAll[Tuple.Map[Tuple.Map[m.MirroredElemTypes, MyTypeClass], Lazy]].toIArray
  
  private inline def productConverter[A](m: Mirror.ProductOf[A]): MyTypeClass[A] = {
    val elementTypeClasses = summonElementTypeClasses(m)
    new MyTypeClass[A] {
      def makeString(a: A): String = {
        val product = a.asInstanceOf[Product]
        elementTypeClasses
          .view
          .zipWithIndex
          .map((obj, i) => {
            val tc = obj.asInstanceOf[Lazy[MyTypeClass[Any]]].value
            tc.makeString(product.productElement(i))
          })
          .mkString("[", ", ", "]")
      }
    }
  }
}

case class Example(a: Int, b: Int) derives MyTypeClass

object Main {
  def main(args: Array[String]): Unit = {
    println("hello world")
    println(summon[MyTypeClass[Example]].makeString(Example(1,2)))
  }
}

Output (click arrow to expand)

scala.MatchError: ClassInfo(ThisType(TypeRef(NoPrefix,module class <empty>)), class Example, List(TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class Object), TypeRef(TermRef(TermRef(NoPrefix,object _root_),object scala),trait Product), TypeRef(ThisType(TypeRef(NoPrefix,module class io)),trait Serializable))) (of class dotty.tools.dotc.core.Types$CachedClassInfo)
	at dotty.tools.dotc.core.Types$TypeLambdaCompanion.toPInfo(Types.scala:3735)
	at dotty.tools.dotc.core.Types$TypeLambdaCompanion.toPInfo(Types.scala:3733)
	at dotty.tools.dotc.core.Types$LambdaTypeCompanion.fromParams$$anonfun$4$$anonfun$1(Types.scala:3721)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Types$LambdaTypeCompanion.fromParams$$anonfun$2(Types.scala:3721)
	at dotty.tools.dotc.core.Types$HKTypeLambda.<init>(Types.scala:3850)
	at dotty.tools.dotc.core.Types$HKTypeLambda$.apply(Types.scala:3956)
	at dotty.tools.dotc.core.Types$HKTypeLambda$.apply(Types.scala:3951)
	at dotty.tools.dotc.core.Types$HKTypeLambda$.apply(Types.scala:3948)
	at dotty.tools.dotc.core.Types$LambdaTypeCompanion.fromParams(Types.scala:3722)
	at dotty.tools.dotc.core.Types$HKTypeLambda$.fromParams(Types.scala:3968)
	at dotty.tools.dotc.typer.TypeAssigner.assignType(TypeAssigner.scala:467)
	at dotty.tools.dotc.typer.TypeAssigner.assignType$(TypeAssigner.scala:19)
	at dotty.tools.dotc.typer.Typer.assignType(Typer.scala:106)
	at dotty.tools.dotc.typer.Typer.typeIndexedLambdaTypeTree(Typer.scala:1921)
	at dotty.tools.dotc.typer.Typer.typedLambdaTypeTree(Typer.scala:1926)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2720)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2756)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:118)
	at dotty.tools.dotc.typer.Inliner$InlineTyper.typedUnadapted(Inliner.scala:1622)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2821)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2825)
	at dotty.tools.dotc.typer.Typer.typedArg$1(Typer.scala:1882)
	at dotty.tools.dotc.typer.Typer.$anonfun$25(Typer.scala:1886)
	at dotty.tools.dotc.core.Decorators$ListDecorator$.zipWithConserve$extension(Decorators.scala:153)
	at dotty.tools.dotc.core.Decorators$ListDecorator$.zipWithConserve$extension(Decorators.scala:154)

I would expect that the type lambda works here.

This isn't a critical bug since it's easy to replace with two Tuple.Map, but I figured it's good to record an issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions