A call to a macro method is executed during the compiler phase called macro expansion to generate a part of the program—an abstract syntax tree.
The Scala 2.13 macro API is closely tied to the Scala 2.13 compiler internals. Therefore it is not possible for the Scala 3 compiler to expand any Scala 2.13 macro.
In contrast, Scala 3 introduces a new principled approach of metaprogramming that is designed for stability. Scala 3 macros, and inline methods in general, will be compatible with future versions of the Scala 3 compiler. While this is an uncontested improvement, it also means that all Scala 2.13 macros have to be rewritten from the ground up, using the new metaprogramming features.
Macro Dependencies
A Scala 3 module can depend on a Scala 2.13 artifact even if it contains a macro definition but the compiler will not be able to expand its macros. When you try to, it simply returns an error.
Let’s note that using -Xignore-scala2-macros
is helpful to type check the code but it produces incomplete class files.
When this error appears in your project, you have eventually no other choice than upgrading to a Scala 3-compiled version of the macro artifact.
Porting the Macro Ecosystem
While being experimental, the Scala community has largely adopted the Scala 2 macro feature in multiple ways: code generation, optimizations, ergonomic DSLs…
A large part of the ecosystem now depends on Scala 2.13 macros defined in external libraries. Identifying and porting those libraries is key to move the ecosystem forward.
A migration status of many open-source macro libraries is available in this page.
Rewriting a Macro
The new metaprogramming features are completely different from Scala 2. They are comprised of:
- Inline Methods
- Compile-time operations
- Macros
- Quoted code
- Reflection over Abstract Syntax Trees (AST)
Before getting deep into reimplementing a macro you should ask yourself:
- Can I use
inline
and thescala.compiletime
operations to reimplement my logic? - Can I use the simpler and safer expression-based macros?
- Do I really need to access the AST?
- Can I use a match type as return type?
You can learn all the new metaprogramming concepts by reading the Macros in Scala 3 tutorial.
Cross-building a Macro Library
You have written a wonderful macro library and you would like it to be available in Scala 2.13 and Scala 3. There are two different approaches, the traditional cross-building technique and the more flexible macro mixing technique.
The benefit of macro mixing is that consumers who take advantage of the -Ytasty-reader
option can still use your macros.
You can learn about them by reading these tutorials:
Additional Resources
Blog posts and talks:
Early-adopter projects: