Yes, this is possible, thanks to the magic of whitebox macros: you can just tell the compiler that the return type is c.Expr[Any]
and it'll infer the more precise type.
This behavior shocked me when I first ran into it—it's very, very powerful and very, very scary—but it definitely is intended, and will continue to be supported, although 2.11 will make a distinction between whitebox and blackbox macros, and the former are likely to remain in experimental status longer (if they ever leave it at all).
For example, the following is a quick sketch of what you're asking for (I'm using quasiquotes here via the macro paradise plugin for 2.10, but it would only be a little more verbose without quasiquotes):
import scala.language.experimental.macros
import scala.reflect.macros.Context
def funImpl[T: c.WeakTypeTag](c: Context)(
method: c.Expr[String]
): c.Expr[Any] = {
import c.universe._
val T = weakTypeOf[T]
val methodName: TermName = method.tree match {
case Literal(Constant(s: String)) => newTermName(s)
case _ => c.abort(c.enclosingPosition, "Must provide a string literal.")
}
c.Expr(q"(t: $T) => t.$methodName")
}
def fun[T](method: String) = macro funImpl[T]
And then:
scala> fun[String]("length")
res0: String => Int = <function1>
You can see that the inferred type is exactly what you want, not Any
. You could (and probably should) set the return type of funImpl
to c.Expr[T => Any]
and return something like c.Expr[T => Any](q"_.$methodName")
, but that's essentially just documentation—it doesn't have any effect on how the return type of the macro is inferred in this case.