在scala 2.13中,为什么有时无法推断TypeTags?以及如何从变量符号构造一个?

问题描述

这是一个简单的无形例子:

  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)?

Typetags not working inside of code block scope?

Type aliases screw up type tags?