我正在尝试编写一个使用此要点中描述的吸血鬼方法技巧的类型提供程序宏;这是我的实现的最小模型:
object DeriveFamily {
def minimal: Any = macro DeriveFamilyMacros.minimal
}
object DeriveFamilyMacros {
class body(tree: Any) extends StaticAnnotation
def bodyImpl(c: Context) = {
import c.universe._
val field = c.macroApplication.symbol
val bodyAnn = field.annotations.filter(_.tree.tpe <:< typeOf[body]).head
bodyAnn.tree.children.tail.head
}
def minimal(c: Context): c.Tree = {
import c.universe._
q"""object Foobar { val _x = "X"; @DeriveFamilyMacros.body(Foobar._x) def x: String = macro DeriveFamilyMacros.bodyImpl }; Foobar"""
}
}
这是一个愚蠢的例子,真正的实现试图使用这个技巧来创建派生类型类实例的捆绑,这些实例无需反射调用即可访问。真实版本和这个版本都存在的问题是,如果我在函数中使用它们,它们可以正常工作,但如果我尝试在 aclass
或object
定义的根目录使用它们,它们会使编译器崩溃:
object Working {
def x = {
val foobar = DeriveFamily.minimal
println(foobar.x)
}
x // Prints "X"
}
object NotWorking {
val foobar = DeriveFamily.minimal
println(foobar.x)
/*
[trace] Stack trace suppressed: run last common/test:compileIncremental for the full output.
[error] (common/test:compileIncremental) java.lang.IllegalArgumentException: Could not find proxy for var Foobar$module: runtime.VolatileObjectRef in List(variable Foobar$module, value foobar, Object NotWorking, package <root>) (currentOwner= value <local NotWorking> )
*/
}
任何解决此问题的帮助都将非常受欢迎,谢谢。