3

次の例を検討してください。

class A
object Macros {
  def genA(str: String): A[_] = macro _genA
  def _genA(c: Context)(str: c.Expr[String]): c.Expr[A[_]] = {
    import c.universe._
    c.Expr[A[_]](
      reify { new A[Int] }.tree)
}
// somewhere in code
genA("int") // --> new A[Int]

期待どおりに動作します。ただし、一致を介して式を選択する一致を導入すると、問題が発生します。

class A
object Macros {
  def genA(str: String): A[_] = macro _genA
  def _genA(c: Context)(str: c.Expr[String]): c.Expr[A[_]] = {
    import c.universe._
    c.Expr[A[_]](
      Match(
        str.tree.duplicate,
        List(
          CaseDef(Literal(Constant("int")), EmptyTree,
            reify { new A[Int] }.tree))))
  }
}
// again, somewhere far, far away in the code
genA("int") // it expands to ("int" match { case "int" => new A[Int] })

正常にコンパイルされますが、マクロ展開後に次のエラーが発生します。

found   : rsf.macros.A[Int]
required: rsf.macros.A[_$1] where type _$1
       genA("int")
           ^

同じ式を手動で入力すると、問題なくコンパイルされます。

val a: A[_] = "int" match { case "int" => new A[Int] }

なぜこれが起こるのですか?それを修正する方法はありますか?

編集:

現在、次の回避策を使用しています。

class A
object Macros {
  def genA(str: String): A[_] = macro _genA
  def _genA(c: Context)(str: c.Expr[String]): c.Expr[A[_]] = {
    import c.universe._
    val mtch = c.Expr[A[_]](
      Match(
        str.tree.duplicate,
        List(
          CaseDef(Literal(Constant("int")), EmptyTree,
            reify { new A[Int] }.tree))))
    reify {
      mtch.splice.asInstanceOf[A[_]]
    }
  }
}

しかし、このマクロが実行されるたびに、どこかで子猫が死んでいるように感じます。子猫を救う方法はあるのでしょうか?

4

0 に答える 0