Type of a macro annottee

macros, scala

Solution

When the macro annotation is being expanded, the annottee doesn't have a symbol created for it yet (sometimes it does, but it's not at given). As a result, it cannot be referenced by a symbol/type, only by a tree, e.g. `Ident(TypeName("Foo"))`. Sure, the result of c.typecheck will give you some symbol/type, but it would be usable only for introspection purposes, not as a point of reference.

This approach should work just fine if you steer clear from hygiene problems. If your companion object defines a class/type member called `Foo`, then `Foo` in `Serializer[Foo]` is going to bind to companion's member, not to the original class. At the moment there's no good way of dealing with that (scalac itself has to solve this problem when generating apply/unapplymethods for case classes, but you don't want to know how it's done). We're planning to provide a solution for this, but we'll only start working on it in the next month, so it'll be a while until it lands in trunk or even paradise.

Problem

How do I get the ("current") type of a macro annottee? ``` import scala.annotation.StaticAnnotation import scala.reflect.macros._ import language.experimental.macros class myself extends StaticAnnotation { def macroTransform(annottees: Any*) = macro myselfMacro.impl } object myselfMacro { def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { import c.universe._ val a = annottees.head println(s"static type = ${a.staticType}") println(s"actual type = ${a.actualType}") c.Expr[Any](Literal(Constant())) } } ``` Test: ``` @myself class Foo ``` Output: ``` static type = Nothing actual type = null ``` The reason I want that type is that I want to use it as a type parameter, e.g. `Bar[Foo]` Edit: Ok, so I think the correct approach is like this: ``` def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { import c.universe._ val v = annottees.head.asInstanceOf[ClassDef] val tpe = v.tpe // <- tpe is null as the annotated type is not yet type checked! val tpe2 = if (tpe == null) c.typeCheck(v).tpe // <- fails with a compiler error (assertion failure) else tpe println(s"Type of annottee: $tpe2") ??? } ``` But given this post by Eugene Burmako, it looks like it is currently not possible...

Original source

Related problems