Skip to content

Latest commit

 

History

History
89 lines (65 loc) · 4.35 KB

compatibility-metaprogramming.md

File metadata and controls

89 lines (65 loc) · 4.35 KB
title type description num previous-page next-page
Metaprogramming
section
This section discuss the metaprogramming transition
5
compatibility-runtime
tooling-tour

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.

{% highlight text %} -- Error: /src/main/scala/example/Example.scala:10:45 10 | val documentFormat = Json.format[Document] | ^ |Scala 2 macro cannot be used in Scala 3. See https://dotty.epfl.ch/docs/reference/dropped-features/macros.html |To turn this error into a warning, pass -Xignore-scala2-macros to the compiler {% endhighlight %}

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][inline]
  • [Compile-time operations][compiletime]
  • [Macros][macros]
  • [Quoted code][quotes]
  • [Reflection over Abstract Syntax Trees (AST)][reflection]

Before getting deep into reimplementing a macro you should ask yourself:

  • Can I use inline and the scala.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]({{ site.scala3ref }}/new-types/match-types.html) as return type?

You can learn all the new metaprogramming concepts by reading the [Macros in Scala 3][scala3-macros] 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:

[inline]: {% link _overviews/scala3-macros/tutorial/inline.md %} [compiletime]: {% link _overviews/scala3-macros/tutorial/compiletime.md %} [macros]: {% link _overviews/scala3-macros/tutorial/macros.md %} [quotes]: {% link _overviews/scala3-macros/tutorial/quotes.md %} [reflection]: {% link _overviews/scala3-macros/tutorial/reflection.md %} [scala3-macros]: {% link _overviews/scala3-macros/tutorial/index.md %}