Макрос Tasty Reflection в Scala 3: CyclicReference
Я пытаюсь получить доступ к параметрам метода, который реализуется как макрос.
object Macros {
def impl()(using Quotes): Expr[Unit] = {
import quotes.reflect._
val params: List[List[ValDef]] = {
def nearestEnclosingMethodParams(owner: Symbol): List[List[ValDef]] =
owner match {
case defSym if defSym.isDefDef =>
defSym.tree.asInstanceOf[DefDef].paramss
case _ =>
nearestEnclosingMethod(owner.owner)
}
nearestEnclosingMethodParams(Symbol.spliceOwner)
}
println(params) // I would do something useful with params names and types here
'{()}
}
}
Сайт для звонков может выглядеть примерно так:
object Test {
def foo(a: String, b: Int) = Foo.impl
@main def run(): Unit = {
val x = foo("blah", 24)
()
}
}
object Foo {
inline def impl = ${ Macros.impl() }
}
На данный момент я получаю
CyclicReference
ошибка при расширении макроса на. Я это понимаю
defSym.tree
является циклическим, потому что он включает в себя код текущего раскрывающегося макроса, но мне все еще нужно получить доступ к «древовидной» версии определения метода, чтобы получить доступ к его имени и параметрам без тела метода. Как я могу получить эту информацию без езды на велосипеде?
1 ответ
Эта проблема была исправлена в недавно выпущенной версии Scala 3.0.0-RC1.
с помощью
defSym.tree
в
def foo(a: String, b: Int) = Foo.impl
пример теперь работает нормально и просто использует
EmptyTree
для тела макроса. Вы можете легко извлечь любую необходимую информацию из аргумента метода или иерархии типов, где
foo
определено, что было моим вариантом использования.
DefDef(
foo,
List(
List(
ValDef(
a,
TypeTree[TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class scala)),object Predef),type String)],
EmptyTree
),
ValDef(
b,
TypeTree[TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object scala),class Int)],
EmptyTree
)
)
),
TypeTree[TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Unit)],
EmptyTree
)