2016-04-04 16 views
4

次のコードが失敗する理由の一般的な質問は、すでにansweredでした。しかし、私の質問は、それが不可能な場合、なぜこれはコンパイラエラーではないのですか?ここでunsafeBitCastがコンパイラエラーではないのはなぜですか?

は、最小限の例です:私は、この関数を定義することができますし、コンパイラはunsafeBitCastは常に失敗するにもかかわらず、文句はありません:

func foo() -> [Int] { 
    let arr: [Int?] = [1, 2, 3, 4] 
    guard let barr = arr as? [Int] else { return [] } 
    return barr 
} 

私たちが実際に実行時にfoo()を呼び出そうとするまで、これが失敗しません。

+0

は私がなぜこのクラッシュの質問が回答されているかを確認していないがコンパイルされません。すでにリンクされたスレッドによって。このランタイムクラッシュのさらに小さな例は '[Int?](count:2、repeatedValue:1)は[Int]'です。これは私が奇妙であると信じています。リンクされたスレッドでは、OPは強制アンラッピング( '...!')と強制キャスティング( ''! ')を使用しようとしますが、ここでは ''型表現のチェックを使用するだけで問題を再現できます。私は間違っているかもしれませんが、私の心配するところでは、これはバックエンドの砂糖(ビットキャストの魔法)に起因するバグのような動作のようです。 – dfri

+0

@dfri、本当の答えよりも唯一のメモがあるにもかかわらず、私の '答え'をチェックしてください。 – user3441734

答えて

2

[Int]は[Int?]のサブタイプではないので、コンパイラのバグです。コードはエラーなしでコンパイルするべきではありません。しかし、次のコードは期待どおりに動作するはずです

let i: [Int?] = [1,2,3] 
let d: [Double?] = [1,2,3] 

func foo<T>(arr:[T?]?) -> [T] { 
    guard let barr = arr where T.self == Int.self else { return [] } 
    return barr.flatMap{ $0 } 
} 

print(foo(i), foo(i).dynamicType) 
print(foo(d), foo(d).dynamicType) 
/* 
[1, 2, 3] Array<Int> 
[] Array<Double> 
*/ 

バグ報告を記入してください!さらに興味深いことに、次のコードは、

let j = [Optional(1),Optional(2)] as? [Int] 

しかし

let j = [Optional(1),Optional(2)] 
let k = j as? [Int] 

コンパイルとクラッシュ...

let arr0:[Int?]? = [1,2,3] 

if let r = arr0 where r.dynamicType == [Int].self { 
    print(r, r.dynamicType) 
} else { 
    print("not [Int]") 
} 
// prints 
// not [Int] 

// but 
func foo()->[Int] { 
    let arr0:[Int?]? = [1,2,3] 
    if let r = arr0 where r.dynamicType == [Int].self { 
     print(r, r.dynamicType) 
     // !!!!! ERROR !!!!! 
     // next line doesn't compile wihout flatMap !!!! 
     // 
     // error: cannot convert return expression of type '[Int?]' to return type '[Int]' 
     // 
     // even though that it is clear from the where clause that r type must be [Int] 
     return r.flatMap{ $0 } 
    } else { 
     print("arr0 is not [Int]") 
     return [] 
    } 
} 
foo() // [] and prints: arr0 is not [Int] 
+0

これは間違いなくバグのようです。私のコメントで言及したように、おそらくバックエンドの変換マジックのためです。可能であれば、私は、答えには、 'is'を使って型表現をテストするだけでも、同じ実行時例外を見ることを含めるでしょう。型キャスティングはランタイムエラーを引き起こすことで有名ですが、型表現チェック( 'is')を行うのは一般的に無害です。このような実行時例外(または試行されたビットキャスト)は実際には発生しません。例えば、あなたの 'j'と' k'の例では 'let j = [Optional(1)、Optional(2)]')、 'let k = jは[Int]'と同じランタイム・クラッシュを生じます。 – dfri

+0

はい、同じ行と2行のバージョンを比較してください:-)最初はコンパイルされません。これは問題ありません.2番目のクラッシュ:-) – user3441734

+1

このバグのようです[既にSR-869 )](https://bugs.swift.org/browse/SR-869)。 – dfri