Skip to content

Compiler stackoverflow for recursive implicit materializer #9048

Open
@scabug

Description

@scabug

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:

  1. fail comprehensibly by suggesting the workaround
  2. automatically turn anonymous class into an implicit object

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions