mercredi 15 mars 2017

Scala macro does not compile when code is crafted without reify

I've been working on complex compile-time reflection and have come across the need to craft Scala code manually, using the AST. While experimenting I noticed a weird compilation error which doesn't really make sense to me, so I tried reproducing it on a test project.

I use Scala 2.10.4.

Here's the code:

Macro.scala:

object Macro {
  def reifyTestImpl(c: Context): c.Expr[OffsetDateTime] = {
    import c.universe._
    val expression = reify(OffsetDateTime.now())
    c.echo(c.enclosingPosition, "With reify: " + show(expression.tree))
    c.echo(c.enclosingPosition, "With reify (raw): " + showRaw(expression.tree))
    expression
  }

  def manualAstTestImpl(c: Context): c.Expr[OffsetDateTime] = {
    import c.universe._
    val odtSymbol = typeOf[OffsetDateTime].typeSymbol
    val now = newTermName("now")
    val expression = c.Expr(
      Apply(
        Select(Ident(odtSymbol), now),
        List()
      )
    )
    c.echo(c.enclosingPosition, "Manual:     " + show(expression.tree))
    c.echo(c.enclosingPosition, "Manual (raw):     " + showRaw(expression.tree))
    expression
  }

  def reifyTest = macro reifyTestImpl
  def manualAstTest = macro manualAstTestImpl
}

Tester.scala:

object Tester {
  def main(args: Array[String]): Unit = {
    println(Macro.reifyTest)
    println(Macro.manualAstTest)
  }
}

The output from c.echo is:

With reify: OffsetDateTime.now()
With reify (raw): Apply(Select(Ident(java.time.OffsetDateTime), newTermName("now")), List())
Manual:     OffsetDateTime.now()
Manual (raw):     Apply(Select(Ident(java.time.OffsetDateTime), newTermName("now")), List())

The compilation error I get is value now is not a member of java.time.OffsetDateTime on the call to Macro.manualAstTest.
As the output from the echoes suggests, the two expressions are identical - yet one works (the expression from reify) and the other does not (the expression crafted with apply-select).

What could be the difference between the two?





Aucun commentaire:

Enregistrer un commentaire