gpt4 book ai didi

scala - 为什么 `Some(123).isInstanceOf[Option[List[String]]]` *不*给出未经检查的警告?

转载 作者:行者123 更新时间:2023-12-02 04:42:10 26 4
gpt4 key购买 nike

当使用 .isInstanceOf[GenericType[SomeOtherType]] 时,其中 GenericTypeSomeOtherType 是任意类型(合适的类型),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

但是,如果 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

(回想一下,元组和 =>Tuple2[]Function2[] 泛型类型的语法糖)

为什么没有发出警告? (所有这些都在 Scala REPL 2.9.1 中,带有 -unchecked 选项。)

最佳答案

我查看了 Scala 编译器源代码,发现了一些有趣的东西

scala.tools.nsc.typechecker.Infer

您可以在其中找到警告。如果您仔细查看第 1399 行,会发现:

def checkCheckable(pos: Position, tp: Type, kind: String)

这是生成警告的地方,您会看到一些嵌套方法,包括检查方法:

 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 ")
}
}

虽然我不是 Scala 编译器方面的专家,但我们都应该感谢这些人让代码变得如此不言自明。让我们看看 tp match block 和处理的情况:

  • 如果是单一类型
  • 如果它是类型引用
    • 如果是抽象类型
    • 如果是别名类型
    • 如果为 Null、Nothing 或 Anyval
    • 所有其他情况

如果您查看所有其他案例,会发现有一行也被注释:

else if (arg.typeArgs.nonEmpty) ()   // avoid spurious warnings with higher-kinded types

这准确地告诉您,如果您的类型具有其他类型参数(如 Function2 或 Tuple2),会发生什么情况。检查函数返回单位而不执行任何测试。

我不知道这样做的原因是什么,但您可能想在以下位置打开一个错误 https://issues.scala-lang.org/browse/SI提供您在此处发布的代码作为优秀的测试用例,并引用我在上面复制的 Infer.scala 源代码。

关于scala - 为什么 `Some(123).isInstanceOf[Option[List[String]]]` *不*给出未经检查的警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11554323/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com