宏观注释的类型

时间:2014-01-10 12:57:01

标签: scala macros

如何获得宏观注释的(“当前”)类型?

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()))
  }
}

测试:

@myself class Foo

输出:

static type = Nothing
actual type = null

我想要那种类型的原因是我想将它用作类型参数,例如Bar[Foo]


修改

好的,所以我认为正确的方法是这样的:

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")
  ???
}

但是given this post by Eugene Burmako,看起来像it is currently not possible ...

1 个答案:

答案 0 :(得分:4)

当扩展宏注释时,注释者还没有为它创建一个符号(有时它会这样做,但它没有给定)。结果,它不能被符号/类型引用,只能由树引用,例如Ident(TypeName("Foo"))。当然,c.typecheck的结果会给你一些符号/类型,但它只能用于内省,而不是作为参考点。

如果您避开卫生问题,这种方法应该可以正常工作。如果您的伴随对象定义了名为Foo的类/类型成员,则Foo中的Serializer[Foo]将绑定到随播广告的成员,而不是原始类。目前还没有好办法解决这个问题(在为案例类生成apply / unapply方法时,scalac本身必须解决这个问题,但你不想知道它是如何完成的) 。我们正计划为此提供一个解决方案,但我们只会在下个月开始研究它,所以它会有一段时间,直到它落在行李箱甚至是天堂。