Расширение макроса содержит свободную переменную - PullRequest
0 голосов
/ 10 июля 2019

Мой код компилируется со следующей ошибкой: Macro expansion contains free term variable Hello ... Я сократил это до минимального примера:

class Hello(val hi: String) {
  val xx = reify(hi)
  var yy = q""
}

def setYYImpl(c: Context)(hExpr: c.Expr[Hello]): c.Expr[Hello] = {
  import c.universe._
  val hello = c.eval(c.Expr[Hello](c.untypecheck(hExpr.tree.duplicate)))
  val xxVal = c.internal.createImporter(u).importTree(hello.xx.tree)
  c.Expr(q"""{val h = new Hello("HO"); h.yy=$xxVal; h}""") // it should set `h.yy` to Tree:"HO"
}

def setYY(hExpr: Hello): Hello = macro setYYImpl


setYY(new Hello("HI"))

После проверки аналогичного вопроса: Можно ли избежать этой ошибки переменной времени (возникающей при расширении макроса)?

Я пришел к выводу, что проблема reify(hi), которая относится к значению времени компиляции Hello.hi.

Можно ли обойти эту проблему? reify(hi) возвращает Expr Hello.hi, можно ли как-нибудь удалить префикс Hello.?

1 Ответ

0 голосов
/ 11 июля 2019

Попробуйте заменить

val xx = reify(hi)

с

val xx = Literal(Constant(hi))

т.е. построить дерево вручную (и .importTree(hello.xx.tree) с .importTree(hello.xx)).

(Если это Literal(Constant... только в вашем примере и более сложное дерево в реальном случае использования, в любом случае попробуйте построить его вручную, а не использовать reify.)

Тогда у вас будет другая ошибка

Error: type mismatch;
 found   : String("HI")
 required: reflect.runtime.universe.Tree
  setYY(new Hello("HI"))

потому что ваш макрос возвращает

Expr[Hello]({
  val h = new Hello("HO");
  h.yy = "HI"; // h.yy is q"" i.e. Tree, "HI" is String
  h
})
...