簡體   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