Macro expansion contains free variable

白昼怎懂夜的黑 提交于 2021-01-06 07:25:40

问题


My code compiles with the following error: Macro expansion contains free term variable Hello ... I have reduced it to minimal example:

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"))

After inspecting similar question: Can this free-term-variable error (produced at macro expansion) be avoided?

I have come to conclusion that the problem is reify(hi) which refers to the compile time value Hello.hi.

Is it possible to work around this problem? reify(hi) returns Expr Hello.hi, can I somehow remove the Hello. prefix?


回答1:


Try to replace

val xx = reify(hi)

with

val xx = Literal(Constant(hi))

i.e. build the tree manually (and .importTree(hello.xx.tree) with .importTree(hello.xx)).

(If it's Literal(Constant... only in your example and more complex tree in actual use case, anyway try to build it manually rather than use reify.)

Then you'll have different error

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

because your macro returns

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


来源:https://stackoverflow.com/questions/56977467/macro-expansion-contains-free-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!