Mizunashi
Mizunashi

Reputation: 335

Lambda in scala macros causes NoSuchMethodError exception

I am a beginner of scala, and studying macros.

As I said in the title, when I pass lambda to macros, I get a NoSuchMethodError exception. For instance, below causes a NoSuchMethodError exception.

object ShowGen {
  def apply[T](f: T => String): Show[T]  = macro impl_apply[T]
  def impl_apply[T: c.WeakTypeTag](c: Context)(f: c.Expr[T => String]): c.Expr[Show[T]] = {
    import c.universe._
    val ty = c.weakTypeOf[T]
    c.Expr[Show[T]](
      q"""
      new Show[$ty] {
        override def show(t: $ty): String = $f(t)
      }
      """)
  }
}

trait Show[T] {
  def show(t: T): String
}
object Main extends App {
  implicit val intShow: Show[Int] = ShowGen[Int] {
    n => (n + 1).toString
  }
  implicit class ShowOps[T: Show](t: T) {
    def show: String = implicitly[Show[T]].show(t)
  }  
  println(1.show)  
}

exception's stack trace is

[error] java.lang.NoSuchMethodError: Main$.$anonfun$intShow$1$adapted(Ljava/lang/Object;)Ljava/lang/String;
[error]     at Main$$anon$1.show(Main.scala:3)
[error]     at Main$$anon$1.show(Main.scala:2)
[error]     at Main$ShowOps.show(Main.scala:7)
[error]     at Main$.delayedEndpoint$Main$1(Main.scala:10)
[error]     at Main$delayedInit$body.apply(Main.scala:1)
[error]     at scala.Function0.apply$mcV$sp(Function0.scala:39)
[error]     at scala.Function0.apply$mcV$sp$(Function0.scala:39)
[error]     at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
[error]     at scala.App.$anonfun$main$1$adapted(App.scala:80)
[error]     at scala.collection.immutable.List.foreach(List.scala:392)
[error]     at scala.App.main(App.scala:80)
[error]     at scala.App.main$(App.scala:78)
[error]     at Main$.main(Main.scala:1)
[error]     at Main.main(Main.scala)
[error]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error]     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error]     at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[error] Nonzero exit code: 1

My question is how to prevent this exception and use lambda in macros.

I know similar issue in github, but there are no responses in that issue, so I could not solve by the issue

Environment

java -version :

java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)

scalaVersion in sbt : 2.12.8

Upvotes: 2

Views: 294

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51658

This is a bug

NoSuchMethodError during initialization of adapted function #10554 https://github.com/scala/bug/issues/10554

NoSuchMethodError $adapted #10054 https://github.com/scala/bug/issues/10054

Workaround is to use named function:

val f: Int => String = n => (n + 1).toString
implicit val intShow: Show[Int] = ShowGen[Int](f)

implicit class ShowOps[T: Show](t: T) {
  def show: String = implicitly[Show[T]].show(t)
}

println(1.show) // 2

Upvotes: 1

Related Questions