Closed
Description
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.