2012-07-19 7 views
15

GenericTypeSomeOtherTypeは、(適した種類の)任意の種類がある.isInstanceOf[GenericType[SomeOtherType]]を使用して、Scalaのコンパイラが原因型消去に未チェックの警告を与える:しかし`Some(123).isInstanceOf [Option [List [String]]]` *は*未確認の警告を出さないのですか?

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[]ジェネリック型のシンタックスシュガーであることを思い出してください)

警告が表示されないのはなぜですか? (これらのすべてが-uncheckedオプションで、ScalaのREPL 2.9.1である。)

答えて

19

私はScalaのコンパイラのソースに見ていた、と私はどこにある

scala.tools.nsc.typechecker.Infer 

を見て何か面白いものを発見しました警告を見つけてください。

警告が生成されている場合、あなたがチェック方法など、いくつかのネストされたメソッドを参照され
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 ") 
     } 
    } 

私は専門家ではないですしながら、あなたのような行1399を注意深く見てみるとScalaコンパイラでは、コードを自明にすることに皆さんに感謝すべきです。さんはtp matchブロックと治療例の内側を見てみましょう:

  • そのシングルタイプ
  • 場合は抽象型
  • ある場合は、別名タイプ
  • であれば、それは
    • REF型である場合
    • Null、Nothing、Anyvalの場合
    • その他すべて

あなたが他のすべての場合に見れば、またコメントされている行があります:

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

あなたのタイプは、機能2、またはTuple2などの他のタイプのパラメータを(持っている場合に発生する正確に何を説明します)。チェック機能はテストを実行せずにユニットを返します。

私はその理由のために、これはこの方法で行われていませんが、あなたは優れたテストケースとしてここに掲載コードを提供 https://issues.scala-lang.org/browse/SI でバグを開きたい、とInfer.scalaソースへの参照可能性があります私は上にコピーした。

+8

偉大な調査! –

+0

確かに、良い仕事! – pedrofurla

+1

コンパイラの引用符は+1です。 :-) –

関連する問題