繁体   English   中英

在reify的宏扩展期间的StackOverflowError

[英]StackOverflowError during macro expansion of reify

我有一个使用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类型Object {def():O.type}(ClassInfoType)

所以这回答了为什么问题,但问题仍然存在,是否有办法解决这个问题。

目前,reifier不知道如何重新引用引用被定义的块内定义的内容的类型。 因此错误。

但它与你的例子有什么关系呢? 这是它的工作原理。

为了验证您的代码块,编译器使用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]
})

我最近碰到了同样的问题。 但我无法负担投射对象类型,因为我在另一个宏中使用单例类型来区分(编译时)“变量”。 因此,如果您确实需要重新生成对象,则可以在宏中执行以下操作,以便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")))
  })
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM