Open
Description
Given the following implicit materializer:
package show
import scala.reflect.macros.blackbox
import scala.language.experimental.macros
trait Show[T] {
def show(t: T) : String
}
object Show {
implicit def materializeShow[T] : Show[T] = macro materializeShowImpl[T]
def materializeShowImpl[T: c.WeakTypeTag](c : blackbox.Context) : c.Tree = {
import c.universe._
val tag: WeakTypeTag[T] = implicitly[WeakTypeTag[T]]
val tpe = tag.tpe
val caseAttributes = tpe.members.collect {
case m: MethodSymbol if m.isCaseAccessor => m
}.toList
val implicits = caseAttributes.map { ca =>
q"implicitly[_root_.show.Show[${ca.typeSignature.resultType}]].show(t.$ca)"
}
q"""
new _root_.show.Show[$tpe] {
def show(t: $tpe) : String = {
List(..$implicits).mkString(",")
}
}
"""
}
}
Compiling the following code
case class A( b : B )
case class B( a : A )
implicitly[Show[A]]
will throw a Stackoverflow
Error:scalac: Error: org.jetbrains.jps.incremental.scala.remote.ServerException
java.lang.StackOverflowError
at scala.tools.nsc.typechecker.Contexts$Context.nextOuter(Contexts.scala:619)
at scala.tools.nsc.typechecker.Contexts$Context.implicitss(Contexts.scala:857)
at scala.tools.nsc.typechecker.Contexts$Context.withOuter$1(Contexts.scala:859)
at scala.tools.nsc.typechecker.Contexts$Context.implicitss(Contexts.scala:880)
at scala.tools.nsc.typechecker.Contexts$Context.withOuter$1(Contexts.scala:859)
Is this related to SI-8141?
Update
Although this isn't straightforward there is a workaround as described in there : scalamacros/macrology201@012db5c
val name = TermName(c.freshName())
q"""
implicit object $name extends _root_.show.Show[$tpe] {
[...]
}
$name
"""
I believe it would be less error prone if the macro system would detect this situation and either:
- fail comprehensibly by suggesting the workaround
- automatically turn anonymous class into an implicit object