Scala 反射 - MethodSymbol 擦除警告,除非导入 universe._
Scala Reflection - MethodSymbol erasure warning unless importing universe._
我有一个带有泛型类型参数的 class,我想获取对泛型类型构造函数的引用。
如果我导入整个 scala.reflect.runtime.universe._,而不是导入别名(例如 "ru"),这只会在没有擦除警告的情况下起作用。
我不清楚是什么原因。我怀疑必须从 Universe 将隐式引入范围,但尚未通过 IntelliJ 的隐式工具找到任何相关内容。
谁能告诉我为什么会这样,如果是隐含的,是哪一个?
编译时没有警告:
import scala.reflect.runtime.universe._
class CaseClassesExample[T :TypeTag] {
def doWork: Unit = {
val tpe = weakTypeTag[T].tpe
val ctor = tpe.decls.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor => m
}
}
}
编译时带有 MethodSymbol 的擦除警告:
import scala.reflect.runtime.{universe => ru}
class CaseClassesExample[T : ru.TypeTag] {
def doWork: Unit = {
val tpe = ru.weakTypeTag[T].tpe
val ctor = tpe.decls.collectFirst {
case m: ru.MethodSymbol if m.isPrimaryConstructor => m
}
}
}
警告:
[warn] abstract type pattern reflect.runtime.universe.MethodSymbol is unchecked since it is eliminated by erasure
[warn] case m: ru.MethodSymbol => m.isConstructor && m.isPrimaryConstructor
[warn] ^
拆分导入:
为了缩小范围,我将导入拆分如下 - 有趣的是,IntelliJ 声明第二个导入未使用,但删除它会带回警告:
import scala.reflect.runtime.{universe => ru}
class CaseClassesExample[T : ru.TypeTag] {
def doWork: Unit = {
val tpe = ru.weakTypeTag[T].tpe
import scala.reflect.runtime.universe._
//IntelliJ highlights above import as unused - but removing it brings warning back
val ctor = tpe.decls.collectFirst {
case m: ru.MethodSymbol if m.isPrimaryConstructor => m
}
}
}
原因很简单。 Universe
有一个名为 MethodSymbolTag
的隐式方法(从 Symbols
特性中混入)定义如下:
implicit val MethodSymbolTag: ClassTag[Universe.MethodSymbol]
作用域中 ClassTag[Universe.MethodSymbol]
的存在允许编译器阻止擦除。
您可以通过在第二个代码片段中添加此导入来验证这一点:
import ru.MethodSymbolTag
我有一个带有泛型类型参数的 class,我想获取对泛型类型构造函数的引用。
如果我导入整个 scala.reflect.runtime.universe._,而不是导入别名(例如 "ru"),这只会在没有擦除警告的情况下起作用。
我不清楚是什么原因。我怀疑必须从 Universe 将隐式引入范围,但尚未通过 IntelliJ 的隐式工具找到任何相关内容。
谁能告诉我为什么会这样,如果是隐含的,是哪一个?
编译时没有警告:
import scala.reflect.runtime.universe._
class CaseClassesExample[T :TypeTag] {
def doWork: Unit = {
val tpe = weakTypeTag[T].tpe
val ctor = tpe.decls.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor => m
}
}
}
编译时带有 MethodSymbol 的擦除警告:
import scala.reflect.runtime.{universe => ru}
class CaseClassesExample[T : ru.TypeTag] {
def doWork: Unit = {
val tpe = ru.weakTypeTag[T].tpe
val ctor = tpe.decls.collectFirst {
case m: ru.MethodSymbol if m.isPrimaryConstructor => m
}
}
}
警告:
[warn] abstract type pattern reflect.runtime.universe.MethodSymbol is unchecked since it is eliminated by erasure
[warn] case m: ru.MethodSymbol => m.isConstructor && m.isPrimaryConstructor
[warn] ^
拆分导入:
为了缩小范围,我将导入拆分如下 - 有趣的是,IntelliJ 声明第二个导入未使用,但删除它会带回警告:
import scala.reflect.runtime.{universe => ru}
class CaseClassesExample[T : ru.TypeTag] {
def doWork: Unit = {
val tpe = ru.weakTypeTag[T].tpe
import scala.reflect.runtime.universe._
//IntelliJ highlights above import as unused - but removing it brings warning back
val ctor = tpe.decls.collectFirst {
case m: ru.MethodSymbol if m.isPrimaryConstructor => m
}
}
}
原因很简单。 Universe
有一个名为 MethodSymbolTag
的隐式方法(从 Symbols
特性中混入)定义如下:
implicit val MethodSymbolTag: ClassTag[Universe.MethodSymbol]
作用域中 ClassTag[Universe.MethodSymbol]
的存在允许编译器阻止擦除。
您可以通过在第二个代码片段中添加此导入来验证这一点:
import ru.MethodSymbolTag