scalaabstract-syntax-treescala-macrosscala-2.13

In scala, can a function be defined to have pass-by-AST parameter, such that the input AST of a function can be passed to a macro as-is?


I'll use the shapeless library as an example:

import shapeless.test.illTyped

assuming that I want to wrap the illType function in another function, I've tried 2 different ways to do this:

(by value)

  def shouldTypeError(v: String) = illTyped(v, ".*")

[ERROR] ... : exception during macro expansion: 
scala.MatchError: v (of class scala.reflect.internal.Trees$Ident)
    at shapeless.test.IllTypedMacros.applyImpl(typechecking.scala:43)

(by name)

  def shouldTypeError(v: => String) = illTyped(v, ".*")

[ERROR ... ]: exception during macro expansion: 
scala.MatchError: v (of class scala.reflect.internal.Trees$Ident)
    at shapeless.test.IllTypedMacros.applyImpl(typechecking.scala:43)

So none of them work as intended. Is this possible in the latest scala or dotty?


Solution

  • No. Outer function must a macro too

    def shouldTypeError(v: String): Unit = macro shouldTypeErrorImpl
    
    def shouldTypeErrorImpl(c: blackbox.Context)(v: c.Tree): c.Tree = {
      import c.universe._
      q"""_root_.shapeless.test.illTyped($v, ".*")"""
    }