我有一个使用reify的简单测试宏。它在宏扩展期间导致StackOverflowError。
def test() = macro testimpl
def testimpl(c:Context)():c.Expr[Any] = {
import c.universe._
val o = reify { // StackOverflowError here
object O
O
}
o
}
为什么会这样?可以以某种方式避免吗?
编辑:这是M6发生的事情。我刚用M7尝试过,现在说
实现限制:无法reify类型对象{def():O.type}(ClassInfoType)
所以这回答了为什么问题,但问题仍然存在,是否有办法解决这个问题。
答案 0 :(得分:3)
目前,修订器不知道如何重新引用引用被定义的块内定义的内容的类型。因此错误。
但它与你的例子有什么关系?这是它的工作原理。
为了验证您的代码块,编译器使用def apply[T: AbsTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T]
(在2.10.0-RC1 AbsTypeTag
中的更新已重命名为WeakTypeTag
)来创建Expr类型的对象表达了这个表达方式。然而,在Expr的合同中隐含的是它也捕获了reifee的类型,并且这引起了问题。
因此,您需要一种解决方法。最简单的方法是将片段的最后一行中的O
转换为可再生的内容,例如:写O.asInstanceOf[Object]
。然后,您可以从结果中手动剥离asInstanceOf
部分。
scala> reify { object O; O }
<console>:26: error: implementation restriction: cannot reify type Object{def <init>(): O.type} (ClassInfoType)
reify { object O; O }
^
scala> reify { object O; O.asInstanceOf[Object] }
res1 @ 2d059fd6: reflect.runtime.universe.Expr[Object] =
Expr[java.lang.Object]({
object O extends AnyRef {
def <init>() = {
super.<init>();
()
}
};
O.asInstanceOf[Object]
})
答案 1 :(得分:1)
我最近碰到了同样的问题。但我无法负担投射对象类型,因为我在另一个宏中使用单例类型来区分(编译时)“变量”。因此,如果您确实需要对对象进行reify,则可以在宏中执行以下操作,以便reify返回对象而不是Unit值。
def mkObject(c: Context) = {
import c.universe._
val objectO = reify { object O }
c.Expr(objectO.tree match {
case Block(stats, expr) => Block(stats, Ident(newTermName("O")))
})
}