计算宏中 shapeless.Witness.Aux[T] 类型的表达式失败
Evaluating an expression of type shapeless.Witness.Aux[T] in a macro fails
我正在尝试评估宏中类型 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.this.T;
[error] value value has incompatible type
println(show(typechecked))
的输出是:
{
final class fresh$macro extends AnyRef with shapeless.Witness {
def <init>(): fresh$macro = {
fresh$macro.super.<init>();
()
};
type T = Boolean(true);
private[this] val value: Boolean(true) = true;
<stable> <accessor> def value: Boolean(true) = true
};
new fresh$macro()
}
println(show(untypechecked))
的输出是:
{
final class fresh$macro 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()
}
在我看来,问题是在未类型检查的树中,value
方法的类型为 Boolean
,而 value
字段的类型为 Boolean(true)
,编译器需要两种类型相同。
有什么解决办法吗?这甚至支持在宏中评估宏吗?
顺便说一句:这个项目 https://github.com/fthomas/scala-macro 包含的是一个用于复制这个的最小项目。
由于 https://github.com/milessabin/shapeless/pull/410 中的更改,这个问题在 shapeless 2.2.2 中消失了。
我正在尝试评估宏中类型 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.this.T;
[error] value value has incompatible type
println(show(typechecked))
的输出是:
{
final class fresh$macro extends AnyRef with shapeless.Witness {
def <init>(): fresh$macro = {
fresh$macro.super.<init>();
()
};
type T = Boolean(true);
private[this] val value: Boolean(true) = true;
<stable> <accessor> def value: Boolean(true) = true
};
new fresh$macro()
}
println(show(untypechecked))
的输出是:
{
final class fresh$macro 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()
}
在我看来,问题是在未类型检查的树中,value
方法的类型为 Boolean
,而 value
字段的类型为 Boolean(true)
,编译器需要两种类型相同。
有什么解决办法吗?这甚至支持在宏中评估宏吗?
顺便说一句:这个项目 https://github.com/fthomas/scala-macro 包含的是一个用于复制这个的最小项目。
由于 https://github.com/milessabin/shapeless/pull/410 中的更改,这个问题在 shapeless 2.2.2 中消失了。