When reflecting the foo()
method of the class Cls
we can easily get the concrete return type using the following.
class Cls {
def foo() =
List("A", "B")
}
val classType = ru.typeOf[Cls]
val classMirror = toolbox.mirror.reflectClass(classType.typeSymbol.asClass)
val ctorSymbol = classType.decl(ru.termNames.CONSTRUCTOR).asMethod
val methodSymb = classType.decl(ru.TermName("foo")).asMethod
val ctor = classMirror.reflectConstructor(ctorSymbol)
val instance = ctor()
val im = toolbox.mirror.reflect(instance)
val foo = im.reflectMethod(methodSymb)
println(foo()) // List(A, B)
println(methodSymb.returnType) // List[String]
However, if we define the class Cls
at runtime via the toolbox and then use the same method reflection process, we will only get the abstract return type (List
) of the foo()
method.
import ru._
val tree =
q"""class Cls {
def foo() =
List("A", "B")
}""".asInstanceOf[ru.ClassDef]
val classSymbol = toolbox.define(tree).asClass
val classType = classSymbol.selfType
val classMirror = toolbox.mirror.reflectClass(classType.typeSymbol.asClass)
val ctorSymbol = classType.decl(ru.termNames.CONSTRUCTOR).asMethod
val methodSymb = classType.decl(ru.TermName("foo")).asMethod
val ctor = classMirror.reflectConstructor(ctorSymbol)
val instance = ctor()
val im = toolbox.mirror.reflect(instance)
val foo = im.reflectMethod(methodSymb)
println(foo()) // List("A", "B")
println(methodSymb.returnType) // List
Why do these code snippets produce different results?
How can we reflect the concrete return type of the foo()
method if Cls
is defined at runtime using the toolbox?
I guess the thing is in type erasure.
Try to replace
val classType = classSymbol.selfType
with
val classType = toolbox.eval(q"scala.reflect.runtime.universe.typeOf[$classSymbol]").asInstanceOf[ru.Type]
Then methodSymb.returnType
is List[String]
.