在宏中评估shapeless.Witness.Aux [T]类型的表达式失败

时间:2015-05-25 10:16:09

标签: scala macros scala-macros shapeless scala-2.11

我正在尝试在宏中评估类型shapeless.Witness.Aux[T]的隐式参数,以便使用单例类型T的值。这是一个最小的例子:

import shapeless.Witness
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

object Macro {
  def foo[N](implicit aux: Witness.Aux[N]): Unit = macro fooImpl[N]

  def fooImpl[N: c.WeakTypeTag](c: Context)
                               (aux: c.Expr[Witness.Aux[N]]): c.Expr[Unit] = {
    import c.universe._

    val typechecked = aux.tree
    println("Typechecked tree:")
    println(show(typechecked))

    val untypechecked = c.untypecheck(typechecked)
    println("Untypechecked tree:")
    println(show(untypechecked))

    def eval = c.eval(c.Expr(untypechecked))
    val w = scala.util.Try(eval).getOrElse(eval)
    // now use w.value
    c.Expr[Unit](q"()")
  }
}

但是要编译这个

val w = shapeless.Witness(true)
Macro.foo[w.T]

因以下错误而失败:

[error] overriding value value in trait Witness of type fresh$macro$2.this.T;
[error] value value has incompatible type

println(show(typechecked))的输出是:

{
  final class fresh$macro$2 extends AnyRef with shapeless.Witness {
    def <init>(): fresh$macro$2 = {
      fresh$macro$2.super.<init>();
      ()
    };
    type T = Boolean(true);
    private[this] val value: Boolean(true) = true;
    <stable> <accessor> def value: Boolean(true) = true
  };
  new fresh$macro$2()
}

println(show(untypechecked))的输出是:

{
  final class fresh$macro$2 extends AnyRef with _root_.shapeless.Witness {
    def <init>() = {
      super.<init>();
      ()
    };
    type T = Boolean(true);
    private[this] val value: Boolean(true) = true;
    <stable> <accessor> def value: Boolean = true
  };
  new fresh$macro$2()
}

在我看来,问题在于,在未经检查的树中,value方法具有类型Boolean,而value字段具有类型Boolean(true),并且编译器需要两种类型是一样的。

任何想法如何解决这个问题?是否支持评估宏中的宏?

顺便说一句:这个项目https://github.com/fthomas/scala-macro包含了一个用于复制它的最小项目。

1 个答案:

答案 0 :(得分:0)

由于https://github.com/milessabin/shapeless/pull/410的变化,这个问题因无形2.2.2而消失。