【问题标题】:StackOverflowError during macro expansion of reifyreify宏扩展期间的StackOverflowError
【发布时间】:2012-08-31 07:19:15
【问题描述】:
我有一个使用 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 试了一下,现在显示
实现限制:无法具体化类型Object{def(): O.type} (ClassInfoType)
所以这回答了为什么的问题,但问题仍然是是否有办法解决这个问题。
【问题讨论】:
标签:
scala
macros
scala-2.10
reification
reify
【解决方案1】:
目前,reifier 不知道如何 reify 引用在被 reified 块中定义的事物的类型。因此出现错误。
但这与您的示例有什么关系?这是它的工作原理。
为了具体化您的代码块,编译器使用def apply[T: AbsTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T](在2.10.0-RC1 中更新AbsTypeTag 已重命名为WeakTypeTag)来创建一个具体化表达式的Expr 类型的对象。然而,在 Expr 的合同中隐含的是,它还捕获了被委托人的类型,这导致了问题。
因此,您需要一种解决方法。最简单的方法是将 sn-p 的最后一行中的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]
})
【解决方案2】:
我最近遇到了同样的问题。但是我负担不起转换对象类型,因为我在另一个宏中使用单例类型来区分(编译时)“变量”。因此,如果您确实需要具体化一个对象,您可以在宏中执行以下操作,以便具体化返回对象而不是 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")))
})
}