I wrote a simple annotation macro to expand a type synonym and save the result in a string. It works fine in a block, but does not work when used to declare a class member. Why?
Here's all the code necessary to compile and run.
Client code:
object Client extends App {
type Synonym = Int
/** fails to compile due to TypeCheckException: not found: type Synonym
* should expand to:
*
* val classScope : String = "Int"
*/
// @dealias val classScope : Synonym = ?
/** this works */
val blockScope = {
@dealias val blockScope : Synonym = ?
blockScope
}
println(s"Inside a block, `Synonym` dealiases to `$blockScope`.")
}
Macro implementation:
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
annottees.head.tree match {
case q"val $lhs : $typeTree = $rhs" =>
val tpe = c.typecheck(q"{ ??? : $typeTree }").tpe
val dealiased = tpe.dealias
c.Expr(q"val $lhs : String = ${dealiased.toString}")
}
}