Skip to content

Compiler crash with recursive type matches and quotes #6281

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

Closed
b-studios opened this issue Apr 10, 2019 · 4 comments
Closed

Compiler crash with recursive type matches and quotes #6281

b-studios opened this issue Apr 10, 2019 · 4 comments

Comments

@b-studios
Copy link
Contributor

When generating code that uses matchers to compute types, the code compiles, but running it results in the runtime error:

34 |    def reify[A] given Type[A]   = m => '{ k => ${ Effects[L].reify[E] {   m(   a =>    Effects[L].reflect[E]('k(a))) } }}
   |                                                                                                              ^
   |                                        value apply is not a member of R
   | This location is in code that was inlined at Bug.scala:34

Here is the full example code (sorry for not being able to minimize further):

package examples

import scala.quoted._

object bug extends App {

  val toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
  implied for scala.quoted.Toolbox = toolbox

  sealed trait HList
  sealed trait HNil extends HList
  sealed trait ::[E, T <: HList] extends HList

  type STM[A, L <: HList] = L match {
    case HNil => Expr[A]
    case e :: rs => (Expr[A] => STM[e, rs]) => STM[e, rs]
  }

  type Stm[A, L <: HList] = L match {
    case HNil => A
    case e :: rs => (A => Stm[e, rs]) => Stm[e, rs]
  }

  trait Effects[L <: HList] {
    def reify[A] given Type[A]: STM[A, L] => Expr[Stm[A, L]]
    def reflect[A] given Type[A]: Expr[Stm[A, L]] => STM[A, L]
  }
  implied empty for Effects[HNil] {
    def reify[A] given Type[A] = m => m
    def reflect[A] given Type[A] = m => m
  }
  // for reify, we need type tags for E and also strangely for L.
  implied cons [E, L <: HList] given Effects[L] given Type[E] given Type[L] for Effects[E :: L] {
    def reify[A] given Type[A]   = m => '{ k => ${ Effects[L].reify[E] {   m(   a =>    Effects[L].reflect[E]('k(a))) } }}
    def reflect[A] given Type[A] = m =>    k =>    Effects[L].reflect[E] { m('{ a => ${ Effects[L].reify[E](   k('a)) } })}
  }
  def Effects[L <: HList] given Effects[L]: Effects[L] = the[Effects[L]]

  type RS = Boolean :: RS2
  type RS2 = Int :: String :: HNil

  val m: STM[Int, RS] = k => k('{42})

  // compiles, but results in a runtime error:
  //    println(Effects[RS].reify[Int] { m }.show)
  //
  // the implicit search results in the following value:
  //    val effects = cons[Boolean, RS2] given (cons[Int, String :: HNil] given (cons[String, HNil] given empty))
  //
  // so the above is equivalent to:
  //    println(effects.reify[Int] { m }.show)
  //
  // error:
  //  37 |    def reify[A] given Type[A]   = m => '{ k => ${ Effects[L].reify[E] {   m(   a =>    Effects[L].reflect[E]('k(a))) } }}
  //   |                                                                                                              ^
  //   |                                        value apply is not a member of R
  //   | This location is in code that was inlined at Bug.scala:37

  // manually inlining reify works
  //  val res : Expr[Stm[Int, RS]] = '{ k => ${ Effects[RS2].reify[Boolean] { m(a => Effects[RS2].reflect[Boolean]('k(a))) }}}
  //  println(res.show)
}

On the example: Both STM and Stm are matchers that given a list of types (HList) compute a new type. The resulting type is produced by iterating CPS.

@nicolasstucki nicolasstucki self-assigned this Apr 10, 2019
biboudis added a commit to dotty-staging/dotty that referenced this issue Apr 15, 2019
@nicolasstucki
Copy link
Contributor

From @biboudis minimization I minimized it further to

import scala.quoted._

object Test {

  val toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
  implied for scala.quoted.Toolbox = toolbox

  sealed trait HList
  sealed trait HNil extends HList
  sealed trait ::[E, T <: HList] extends HList

   type Stm[A, L <: HList] = L match {
    case HNil => A
    case e :: rs => (A => Stm[e, rs]) => Stm[e, rs]
  }

  def main(args: Array[String]): Unit = {

    val boom = '{ (x: Int) => (??? : Stm[Int, Int :: Int :: HNil]) }
    val foo: Expr[Int] =
     '{ println(); ${
       boom('{4})('{ (a4: Int) => (k4: Int => Int) => ${ 'k4('a4) } } )('{ (a7: Int)  => a7 })
       } }
    println(foo.show)
  }
}
19 |    val boom = '{ (x: Int) => (??? : Stm[Int, Int :: Int :: HNil]) }
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                              value apply is not a member of R
true
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at dotty.tools.vulpix.ChildJVMMain.runMain(ChildJVMMain.java:40)
        at dotty.tools.vulpix.ChildJVMMain.main(ChildJVMMain.java:47)
Caused by: java.lang.Exception: Could not extract Expr(<pickled tasty>)
        at dotty.tools.dotc.quoted.QuoteDriver.withTree$$

@b-studios
Copy link
Contributor Author

Great! Thanks for looking at the issue

@biboudis biboudis changed the title Interaction between Matcher and Meta Programming Compiler crash with recursive type matches and quotes Apr 17, 2019
@nicolasstucki nicolasstucki removed their assignment May 2, 2019
@b-studios
Copy link
Contributor Author

Even after merging #6322 this issue still occurs, so I guess it was not the reason for it.

@nicolasstucki
Copy link
Contributor

@b-studios it looks like it is fixed now. I added the full code that is in the first snippet in #6840 and all seemed to work.

liufengyun added a commit that referenced this issue Jul 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants