简体   繁体   English

在reify的宏扩展期间的StackOverflowError

[英]StackOverflowError during macro expansion of reify

I have a simple test macro that uses reify. 我有一个使用reify的简单测试宏。 It causes a StackOverflowError during macro expansion. 它在宏扩展期间导致StackOverflowError。

def test() = macro testimpl

def testimpl(c:Context)():c.Expr[Any] = {
  import c.universe._
  val o = reify { // StackOverflowError here
    object O
    O
  }
  o
}

Why does this happen? 为什么会这样? Can it somehow be avoided? 可以以某种方式避免吗?

EDIT: This is what happens with M6. 编辑:这是M6发生的事情。 I just tried it with M7 and now it says 我只是用M7尝试过,现在它说

implementation restriction: cannot reify type Object{def (): O.type} (ClassInfoType) 实现限制:无法reify类型Object {def():O.type}(ClassInfoType)

So that answers the why question, but the question still remains whether there is a way to work around this. 所以这回答了为什么问题,但问题仍然存在,是否有办法解决这个问题。

Currently the reifier doesn't know how to reify types that reference things defined inside the block being reified. 目前,reifier不知道如何重新引用引用被定义的块内定义的内容的类型。 Hence the error. 因此错误。

But what does it have to do with your example? 但它与你的例子有什么关系呢? Here's how it works. 这是它的工作原理。

To reify your block of code, the compiler uses def apply[T: AbsTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] (upd. in 2.10.0-RC1 AbsTypeTag has been renamed to WeakTypeTag ) to create an object of type Expr that reifies the expression. 为了验证您的代码块,编译器使用def apply[T: AbsTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] (在2.10.0-RC1中AbsTypeTag已重命名为WeakTypeTag )创建一个Expr类型的对象,用于表达表达式。 However implicit in the contract of Expr is that it also captures the type of the reifee, and that gives rise to the problem. 然而,在Expr的合同中隐含的是它也捕获了reifee的类型,并且这引起了问题。

Therefore you need a workaround. 因此,您需要一种解决方法。 The simplest one would be to cast O in the last line of the snippet to something reifiable, eg to write O.asInstanceOf[Object] . 最简单的方法是将片段的最后一行中的O为可再生的内容,例如写入O.asInstanceOf[Object] Then you can manually strip off the asInstanceOf part from the result. 然后,您可以从结果中手动剥离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]
})

I bumped into the same issue lately. 我最近碰到了同样的问题。 But I couldn't afford casting the object type, as I used the singleton type within a other macro to distinguish between (compile time) "variables". 但我无法负担投射对象类型,因为我在另一个宏中使用单例类型来区分(编译时)“变量”。 So if you really need to reify an object, you can do the following within a macro so reify return the object instead of a Unit value. 因此,如果您确实需要重新生成对象,则可以在宏中执行以下操作,以便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