Skip to content
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

Type Lambda Crashes Compiler #13460

Closed
AugustNagro opened this issue Sep 2, 2021 · 1 comment · Fixed by #13658
Closed

Type Lambda Crashes Compiler #13460

AugustNagro opened this issue Sep 2, 2021 · 1 comment · Fixed by #13658

Comments

@AugustNagro
Copy link
Contributor

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.

@soronpo
Copy link
Contributor

soronpo commented Sep 3, 2021

Same error on 3.1.0-RC1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants