Mec*_*ail 15 warnings scala unchecked compiler-warnings type-erasure
当使用.isInstanceOf[GenericType[SomeOtherType]]
,where GenericType
和SomeOtherType
是任意类型(适当类型)时,Scala编译器会因类型擦除而提供未经检查的警告:
scala> Some(123).isInstanceOf[Option[Int]]
<console>:8: warning: non variable type-argument Int in type Option[Int] is unchecked since it is eliminated by erasure
Some(123).isInstanceOf[Option[Int]]
^
res0: Boolean = true
scala> Some(123).isInstanceOf[Option[String]]
<console>:8: warning: non variable type-argument String in type Option[String] is unchecked since it is eliminated by erasure
Some(123).isInstanceOf[Option[String]]
^
res1: Boolean = true
Run Code Online (Sandbox Code Playgroud)
但是,如果SomeOtherType
它本身是泛型类型(例如List[String]
),则不会发出警告:
scala> Some(123).isInstanceOf[Option[List[String]]]
res2: Boolean = true
scala> Some(123).isInstanceOf[Option[Option[Int]]]
res3: Boolean = true
scala> Some(123).isInstanceOf[Option[List[Int => String]]]
res4: Boolean = true
scala> Some(123).isInstanceOf[Option[(String, Double)]]
res5: Boolean = true
scala> Some(123).isInstanceOf[Option[String => Double]]
res6: Boolean = true
Run Code Online (Sandbox Code Playgroud)
(记得,元组和=>
对于语法糖Tuple2[]
和Function2[]
泛型类型)
为什么没有发出警告?(所有这些都在Scala REPL 2.9.1中,带有-unchecked
选项.)
Edm*_*984 19
我看了一下Scala编译器的来源,我发现了一些有趣的东西
scala.tools.nsc.typechecker.Infer
Run Code Online (Sandbox Code Playgroud)
这是你发现警告的地方.如果你仔细看第1399行:
def checkCheckable(pos: Position, tp: Type, kind: String)
Run Code Online (Sandbox Code Playgroud)
这是生成警告的位置,您会看到一些嵌套方法,包括check方法:
def check(tp: Type, bound: List[Symbol]) {
def isLocalBinding(sym: Symbol) =
sym.isAbstractType &&
((bound contains sym) ||
sym.name == tpnme.WILDCARD || {
val e = context.scope.lookupEntry(sym.name)
(e ne null) && e.sym == sym && !e.sym.isTypeParameterOrSkolem && e.owner == context.scope
})
tp match {
case SingleType(pre, _) =>
check(pre, bound)
case TypeRef(pre, sym, args) =>
if (sym.isAbstractType) {
if (!isLocalBinding(sym)) patternWarning(tp, "abstract type ")
} else if (sym.isAliasType) {
check(tp.normalize, bound)
} else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) {
error(pos, "type "+tp+" cannot be used in a type pattern or isInstanceOf test")
} else {
for (arg <- args) {
if (sym == ArrayClass) check(arg, bound)
else if (arg.typeArgs.nonEmpty) () // avoid spurious warnings with higher-kinded types
else arg match {
case TypeRef(_, sym, _) if isLocalBinding(sym) =>
;
case _ =>
patternWarning(arg, "non variable type-argument ")
}
}
}
check(pre, bound)
case RefinedType(parents, decls) =>
if (decls.isEmpty) for (p <- parents) check(p, bound)
else patternWarning(tp, "refinement ")
case ExistentialType(quantified, tp1) =>
check(tp1, bound ::: quantified)
case ThisType(_) =>
;
case NoPrefix =>
;
case _ =>
patternWarning(tp, "type ")
}
}
Run Code Online (Sandbox Code Playgroud)
虽然我不是Scala编译器的专家,但我们都应该感谢这些人使代码变得如此不言自明.让我们看看tp match
块和处理过的案例:
如果你看看所有其他情况,还有一行也被注释:
else if (arg.typeArgs.nonEmpty) () // avoid spurious warnings with higher-kinded types
Run Code Online (Sandbox Code Playgroud)
这告诉你如果你的类型有其他类型参数(如Function2或Tuple2)会发生什么.检查功能返回单元而不执行任何测试.
我不是出于这个原因这样做的,但你可能想在https://issues.scala-lang.org/browse/SI上打开一个错误, 提供你在这里发布的代码作为一个优秀的测试用例,并且我在上面复制的Infer.scala源代码的引用.
归档时间: |
|
查看次数: |
815 次 |
最近记录: |