问题描述
这是一个简单的无形例子:
it("from Witness") {
val ttg = implicitly[TypeTag[Witness.Lt[String]]]
val ctg = implicitly[classtag[Witness.Lt[String]]]
}
it("... from macro") {
val ttg = implicitly[TypeTag[Witness.`1`.T]]
val ctg = implicitly[classtag[Witness.`1`.T]]
}
it("... doesn't work") {
val ttg = implicitly[TypeTag[w1.T]] // Failed!
val ctg = implicitly[classtag[w2.T]]
}
第二个和第三个 it
块具有非常相似的字节码(在调用了 Witness.?
宏之后),但一个成功,一个失败:
[Error] /home/peng/git-spike/scalaspike/common/src/test/scala/com/tribbloids/spike/scala_spike/Reflection/InferTypeTag.scala:55: No TypeTag available for com.tribbloids.spike.scala_spike.Reflection.InferTypeTag.w1.T
这是什么原因造成的?我该如何规避这个问题?
解决方法
如果您打开 scalacOptions += "-Xlog-implicits"
,您会看到
val w1 = Witness(1)
val ttg = implicitly[TypeTag[w1.T]] // doesn't compile
//materializing requested reflect.runtime.universe.type.TypeTag[App.w1.T] using scala.reflect.api.`package`.materializeTypeTag[App.w1.T](scala.reflect.runtime.`package`.universe)
//scala.reflect.api.`package`.materializeTypeTag[App.w1.T](scala.reflect.runtime.`package`.universe) is not a valid implicit value for reflect.runtime.universe.TypeTag[App.w1.T] because:
//failed to typecheck the materialized tag:
//cannot create a TypeTag referring to type shapeless.Witness.<refinement>.T local to the reifee: use WeakTypeTag instead
//No TypeTag available for App.w1.T
所以尽量按照推荐使用 WeakTypeTag
val w1 = Witness(1)
val ttg2 = implicitly[WeakTypeTag[w1.T]] // compiles
In Scala,why it is impossible to infer TypeTag from type alias or dependent type?
Why there is no TypeTag available in nested instantiations (when interpreted by scala code runner)?