"macro implementation reference has wrong shape" in the Scala Documentation examples

scala, scala-macros, scala-quasiquotes

Solution

`scala Foo.scala` wraps the code that you feed to it in an anonymous class. As a result, something like:

import scala.reflect.macros.Context
import scala.language.experimental.macros

object debug {
  def apply[T](x: T): T = macro impl
  def impl(c: Context)(x: c.Tree): c.Tree = ???
}

Gets transformed into:

[[syntax trees at end of                    parser]] // Test.scala
package <empty> {
  object Main extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    def main(args: Array[String]): scala.Unit = {
      final class $anon extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        import scala.reflect.macros.Context;
        import scala.language.experimental.macros;
        object debug extends scala.AnyRef {
          def <init>() = {
            super.<init>();
            ()
          };
          <macro> def apply[T](x: T): T = impl;
          def impl(c: Context)(x: c.Tree): c.Tree = $qmark$qmark$qmark
        }
      };
      new $anon()
    }
  }
}

However, macro implementations must be defined in static object or bundles, which is what the error messages tries to say:

/Users/xeno_by/Projects/211x/sandbox/Test.scala:5: error: macro implementation reference has wrong shape. required:
macro [<static object>].<method name>[[<type args>]] or
macro [<macro bundle>].<method name>[[<type args>]]
  def apply[T](x: T): T = macro impl
                                ^
one error found

Unfortunately, if something is put into inside an anonymous class, it's no longer static, which means that `scala Foo.scala`-style development is incompatible with macros. Consider using alternatives, e.g. `scalac` or `sbt`.

Problem

The following macro is pasted from http://docs.scala-lang.org/overviews/quasiquotes/usecases.html: ``` import reflect.macros.Context import language.experimental.macros val universe = reflect.runtime.universe; import universe._ import reflect.runtime.currentMirror import tools.reflect.ToolBox val toolbox = currentMirror.mkToolBox() object debug { def apply[T](x: =>T): T = macro impl def impl(c: Context)(x: c.Tree) = { import c.universe._ val q"..$stats" = x val loggedStats = stats.flatMap { stat => val msg = "executing " + showCode(stat) List(q"println($msg)", stat) } q"..$loggedStats" } } ``` It produces this error message in Scala 2.11.1: ``` Q.scala:9: error: macro implementation reference has wrong shape. required: macro [<static object>].<method name>[[<type args>]] or macro [<macro bundle>].<method name>[[<type args>]] def apply[T](x: =>T): T = macro impl ^ ``` I've tried varying the code in numerous ways (`import reflect.macros.whitebox.Context`, `import reflect.macros.blackbox.Context`, putting `scala.` at the start of each import, making the arguments consistently by-name or consistently by-value, `macro impl[T]`, getting rid of the type parameter, `macro debug.impl`, putting the `apply` after the `impl`, and more) with no success. What am I doing wrong? Is it something in the imports? Those come (mostly) from a different web page, http://docs.scala-lang.org/overviews/quasiquotes/setup.html. The same error occurs on both of the other example macros from that page: ``` object Macro { def apply(x: Int): Int = macro impl def impl(c: Context)(x: c.Expr[Int]): c.Expr[Int] = { import c.universe._ c.Expr(q"$x + 1") } } object Macro { def apply(x: Int): Int = macro impl def impl(c: Context)(x: c.Tree) = { import c.universe._ q"$x + 1" } } ```

Original source