There is currently a discussion happening on github which was requested to be moved to contributors regarding the new behaviour of experimental language features.
The new intended behaviour being talked about is that if a new language feature in Scala 3 is considered experimental, there is no easy way to opt out of this. In other words, when features are marked experimental with the @experimental
annotation, this forces the Scala 3 compiler to enforce that all transitive call sites of that initial @experimental
also need to add @experimental
.
Specifically in the context of Macro Annoations, if you define a macro annotation i.e.
// Note that we are forced to put @experimental here due to MacroAnnotation
// having @experimental
@experimental class myAnnotation extends MacroAnnotation
We also have to add @experimental
to the user code that happens to call myAnnotation
, i.e.
@myAnnotation def something
will not compile, you have to do
@experimental @myAnnotation def something
instead (although it is important to note that to reduce the noise (if possible) you can add the @experimental
annotation to a top level object/class although you can then counter argue that you are marking your entire object as @experimental
when in fact it may only be in a few places.
In case its not clear, its also entirely intended that you cannot get around this, i.e. unlike in Scala 2 where you could add scalac flags and/or experimental features were considered a warning this in Scala 3 you have to add the annotation unless you use a snapshot/non mainline compiler.
This kind of designed has surfaced some consequences which have been raised in the earlier mentioned thread. The first one which is specific to macro annotations is that the forced transitive application of @experimental
can be considered excessive because for the caller (i.e. âuserâ) of the macro annotation, the fact that its @experimental
is unnecessary. While for language features like direct style this behaviour is understandable, for macro annotations the user doesnât really care how a macro annotation is implemented so even if the entire design of macro annotations is change its irrelevant (although it is to be noted that hypothetically speaking macro annotations could even be removed at some point).
The other problem is a specific one for library authors when it comes to creating code that uses macro annotations which are cross compiled both to Scala 2 and Scala 3. Often the goal of such libraries is that the user can write cross compatible Scala code (i.e. code that cross compiles both to Scala 2 and Scala 3) and with the current design this isnât possible because of that forced @experimental
annotation. This is because there is no such thing as an @experimental
annotation in Scala and although this can be worked around by either creating a stub scala.annotation.experimental
just for Scala 2 I have reservations that this would be expected behaviour.
Authors of izumi-reflect/airframe which are such libraries that are designed to support multiple Scala versions this way have also stated the same concerns.
My personal 2 cents are specifically in the case of macros/macros annotation, the transitive behaviour of forcing the @experimental
annotation is excessive and has unintended consequences. While I understand that macro/macro annotations could even be removed/significantly changed at some point I also find this highly unlikely considering a lot of what can be considered critical Scala libraries actually rely on these features.