简体   繁体   中英

Macro expansion contains free variable

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?

Try to replace

val xx = reify(hi)

with

val xx = Literal(Constant(hi))

ie 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
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM