Scala 从编译到运行时具体化ValDef

Scala 从编译到运行时具体化ValDef,scala,reflection,scala-macros,Scala,Reflection,Scala Macros,我想将ValDef具体化到运行时,但我不直接工作。如果我将ValDef封装到一个块中,那么一切都会完美工作,如以下示例所示: case class Container(expr: Expr[Any]) def lift(expr: Any): Container = macro reifyValDef def reifyValDef(c: Context)(expr: c.Expr[Any]): c.Expr[Container] = { import c.universe._ ex

我想将ValDef具体化到运行时,但我不直接工作。如果我将ValDef封装到一个块中,那么一切都会完美工作,如以下示例所示:

case class Container(expr: Expr[Any])

def lift(expr: Any): Container = macro reifyValDef

def reifyValDef(c: Context)(expr: c.Expr[Any]): c.Expr[Container] = {
  import c.universe._
  expr.tree match {
  case Block(List(v: ValDef), _) =>
    val asBlock = q"{$v}"
    val toRuntime = q"scala.reflect.runtime.universe.reify($asBlock)"
    c.Expr[Container](q"Container($toRuntime)")
  }
}

lift {
  val x: Int = 10
}
如果我直接使用v,而不是将其包装成块,我会得到错误:

Error:(10, 11) type mismatch; found : required: Any Note that extends Any, not AnyRef. Such types can participate in value classes, but instances cannot appear in singleton types or in reference comparisons. val x: Int = 10 ^ 错误:(10,11)类型不匹配; 发现: 必填项:任何 注意,它扩展了Any,而不是AnyRef。 此类类型可以参与值类,但不包括实例 不能出现在单例类型或引用比较中。 val x:Int=10 ^
它只是没有直接与ValDefs一起工作,还是我的代码有问题?

这是反射API中已知的问题之一。从技术上讲,定义不是表达式,因此不能直接将其作为参数传递给函数。将定义包装在块中是寻址块的正确方法

错误消息当然令人困惑,但它确实有一些扭曲的含义。为了表明定义本身没有类型,相应的
树的
tpe
字段设置为
NoType
。然后根据
Any
检查宏参数的类型,检查失败(因为
NoType
是一种特殊类型,与任何类型都不兼容),因此会打印标准错误消息。笨拙的打印输出是预打印程序在这种奇怪情况下的行为的产物