Closed
Description
We had a discussion before about annotation macros, the idea then was to transform the following annotation macros:
class main extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
body
}
}
to:
class main extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
main$inline.meta3(defn)
}
}
object main$inline {
def meta3(prefix:scala.meta.Stat)(defn: scala.meta.Stat): scala.meta.Stat = body
}
There are some problems with the scheme above. For example, given the code:
@main
class Test {
println("hello, world!")
}
The namer has a difficulty to determine whether @main
is a macros or not and how to expand it. It needs to do as least follows:
- resolve the name
main
to a symbol (typedIndent
)- problem 1: it doesn't work reliably if
main
is defined in the same compilation run
- problem 1: it doesn't work reliably if
- check if
main
extendsscala.annotation.StaticAnnotation
- check if
main
has a memberinline def apply(defn: Any): Any
, and rhs begins withmeta
.- problem 2: Inspect syntactic tree to know some info about a compiled symbol is counter-intuitive, the info should be part of the symbol. Also, ASTs are not always available if
@main
is defined without tasty (e.g. Scala2).
- problem 2: Inspect syntactic tree to know some info about a compiled symbol is counter-intuitive, the info should be part of the symbol. Also, ASTs are not always available if
- inspect the body of
meta
to get the implementation method.- problem 3: This seems to incur unnecessary complexity, a simpler convention can be that the implementation is defined in
main$inline.meta
, thus no need to inspect ASTs, which can impose a performance penalty by deserializing tasty.
- problem 3: This seems to incur unnecessary complexity, a simpler convention can be that the implementation is defined in
It seems that annotation macros are somewhat special, different from def macros, inlining never happens for annotation macros. It seems to me that current paradise
implementation of annotation macros is simpler (avoids problem 2 & 3), it translates the code:
class main extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
body
}
}
to:
class main extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = ???
}
object main$inline {
def apply(prefix:scala.meta.Stat)(defn: scala.meta.Stat): scala.meta.Stat = body
}
My question is:
- Can we assume annotation macros are always compiled in a different run (problem 1)?
- Can we follow paradise's way of handling annotation macros (simpler, avoids problem 2 & 3)?
- During annotation macros transform, can we only transform
inline def apply(defn: Any): Any = meta {...}
, and ignore other possibleinline/meta
methods, as they don't make sense for annotation macros?
WDYT @odersky @xeno-by @DarkDimius ?