2

Suppose I've got two macro-annotated classes, and after their fields are defined during expansion, one depends on the other:

@Annotation case class A(i: Int) @Annotation case class B(a: A)

I need A to be expanded before B, but the order of their definition does not ensure that.

For example, a reference to B as a type-parameter to an object in an unrelated compilation unit, such as:

class X{val b = B(A(1))} in one file and class Y{Z[B]} in another,

causes B to be expanded first and thus my compilation fails.

What determines the order of macro expansion in this case? Is there any way to enforce a desired order?

Thanks for your input,

Julian

Julian Peeters
  • 853
  • 1
  • 6
  • 19
  • Could you elaborate on your use case? What does the `Annotation` macro do? Maybe there's some code that you could share? – Eugene Burmako May 09 '14 at 11:53
  • Thanks for the response, and apologies for the delay in mine. The code makes case classes Avro-serializable, partly by turning it into a Schema object and storing it in case we need it again. If a field's type is another case class, then that other case class needs to have been already stored. – Julian Peeters May 15 '14 at 05:54
  • [This branch](https://github.com/julianpeeters/avro-scala-macro-annotations/tree/expansion_order) is a minimized example showing that the order of expansion depends not only on being referenced first in a given file, but also on the lexical order of the file names in which it's referenced. I.e., rename `A.scala` to `Z.scala` so it follows `Test.scala` lexically, and compilation will succeed. – Julian Peeters May 15 '14 at 05:55

1 Answers1

2

typecheck was the solution for me.

If type A (A's tree.tpe) is used in compile-time reflection before its macro has been expanded, it can be expanded as soon as it is stumbled upon:

import c.universe._
import Flag._

def expandType(typeTree: Tree) = {
  c.typecheck(q"type T = $typeTree") match {
    case x @ TypeDef(mods, name, tparams, rhs)  => rhs.tpe
  }
}
Julian Peeters
  • 853
  • 1
  • 6
  • 19