1

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?

Ford O.
  • 1,394
  • 8
  • 25

1 Answers1

2

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
})
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66