I am currently implementing a macro annotation called getInline and I am hitting an issue where specifically for Scala 3 macro annotations I can't seem to write such a macro.
Given we have the following macro annotation
@experimental class getInline extends MacroAnnotation {
override def transform(using quotes: Quotes)(
tree: quotes.reflect.Definition
): List[quotes.reflect.Definition]
and with the following body where we implement the macro
tree match {
case e@ DefDef(name, params, tpt, rhs) =>
val flagsWithInline = e.symbol.flags | Flags.Inline
val methodWithInline = Symbol.newMethod(tree.symbol.owner,
e.name,
e.symbol.typeRef,
flagsWithInline,
e.symbol.privateWithin.map(_.termSymbol).getOrElse(Symbol.noSymbol)
)
???
case e: ValDef =>
val flagsWithInline = e.symbol.flags | Flags.Inline
val valWithInline = Symbol.newVal(tree.symbol.owner,
e.name,
e.symbol.typeRef,
flagsWithInline,
e.symbol.privateWithin.map(_.termSymbol).getOrElse(Symbol.noSymbol)
)
???
}
}
The core problem I have is how to return a new AST tree (in place of ???) with the methodWithInline and valWithInline respectively. Assuming we have the following code that calls the macro annotation
@getInline final def myVal = 5
The tree returned by methodWithInline using the .show method is
inline final def myVal: org.mdedetrich.Test.myVal = 5
Which is exactly what we want. The problem is that if we return methodWithInline as is using List(DefDef(methodWithInline, _ => e.rhs)) as the implementation of the macro annotation then the following error message appears
[error] |Transformed tree for @getInline final def myVal: Int = 5 was not return by `(new org.mdedetrich.getinline.getInline()).transform(..)` during macro expansion
It appears that the proper way to do this is to use DefDef.copy on the current tree (which in our case is represented by the value e). The problem here is that DefDef.copy does not appear to accept an altered list of Flags (represented by the flagsWithInline variable).