宏扩展包含自由变量

Macro expansion contains free variable

我的代码编译时出现以下错误: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"))

检查类似问题后:Can this free-term-variable error (produced at macro expansion) be avoided?

我得出结论,问题是reify(hi),它指的是编译时值Hello.hi

是否可以解决此问题? reify(hi) returns Expr Hello.hi, 我能以某种方式删除 Hello. 前缀吗?

尝试替换

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

因为你的宏 returns

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