scalameta/scalameta — pull request #44 by xeno-by (2014-10-02 12:51:47+00:00)
Title: begone, whitebox macros!

tl;dr. Whitebox macros are very hard to implement in a robust way,
so we've decided to not include them in the M1 release of scala.meta.
The decision is not final, but at the moment we definitely don't see
a way to make this work.

Lazy initialization of member signatures employed by scalac to deal with
cyclic references makes it almost impossible to deterministically perform
non-local explorations of the program being compiled. For instance, doing
something as natural as requesting a list of members of a given type might,
depending on the order of program elements and on the amount of type annotations
in the program: 1) succeed, 2) give a spurious cyclic error, 3) give a legitimate
cyclic error. More complex operations (like getting a list of known
subclasses of a class) add another possibility to the crazy mix:
4) give an incomplete / incorrect result.

And it's not just scalac (scalac does make things harder than it should be,
but the root cause of the problem lies elsewhere). As long as we can have
cyclic references between program elements, sufficiently powerful whitebox macros
will have the potential of inducing unresolvable cyclic dependencies
(e.g. a macro in class A needs a list of members of class B to generate
some additional members for A + the same macro in class B needs a list
of members of class A). I've been thinking about this on and off since
http://stackoverflow.com/questions/19954776/scala-macro-annotations-c-typecheck-of-annotated-type-causes-stackoverflowerror
and still haven't found a robust and easy to understand solution to the
problem.

One of the main goals of scala.meta is providing a robust metaprogramming API,
devoid of the usual inconsistencies plaguing scala.reflect. In order to achieve that,
we have to be very mindful of the features we support, starting from a
well-understood core and carefully moving forward from there. Therefore,
even though I'm very unhappy about that, I have to remove whitebox macros
from the roadmap for the M1 release. This is not a final decision in the sense
that if a solution to making whitebox macros robust is found, then it will
definitely be considered. However at the moment we just can't see how scala.meta
can incorporate whitebox macros and stay faithful to its goals.

It should be mentioned that not having whitebox macros renders macros
unsuitable for some important use cases (some of which are outlined in
http://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html#codifying-the-distinction),
but I hope that together we'll find ways to work around, like we always did.

A reasonable possibility would be to explore whitebox macros that can't
do semantic operations. We have a particularly elegant way of doing that
in the new API - just don't provide the implicit host argument to a macro,
and they are guaranteed to not be able to do anything. It will have to be
seen how far this can get us, and whether we can implement this in M1.