Swift 3.1で死んだコードまとめ

  • 75
    いいね
  • 0
    コメント

Swiftのリリースの度に型が破壊されるたるのんです、こんにちは。
Swift3.1への移行の調子はいかがでしょうか?すこぶる順調でしょうか?僕は大変でした。
ということでSwift3.1でコンパイルできなくなったコードまとめ。

switchを使ってenumからprotocolを複数のパターンで取り出す

protocol X {}
extension String: X {}

enum A {
    case hoge(X)
    case fuga(X)
}

let a = A.hoge("hello")

switch a {
case .hoge(let x), .fuga(let x):
    print(x)
default:
    break
}

Swiftのswitchは有能で、一つのcaseに複数のパターンを列挙し同じ型なら同じ変数として取り出すことが出来ます。
が、3.1ではProtocol型であった場合、コンパイラがクラッシュします。
地道にcaseを分けてください。

報告済み
https://bugs.swift.org/browse/SR-4417

NSErrorを拡張してError型をキャストするとNSErrorに強制的にキャストされる

import Foundation

protocol MyCustomErrorProtocol {
    var hoge: Int { get }
}

struct MyCustomError: Error, MyCustomErrorProtocol {
    var hoge: Int {
        return 1
    }
}

extension NSError: MyCustomErrorProtocol {
    var hoge: Int {
        return 0
    }
}

let error: Error = MyCustomError()

if let cError = error as? MyCustomErrorProtocol {
    cError.hoge // 0 (If Swift 3.0 then 1)
}

かなりヤバいバグです。
同じ型でNSErrorと任意のErrorを拡張しているとハマります。
もし貴方がSwift3.1を使っているなら、絶対にNSErrorを拡張してはいけません。

報告済み
https://bugs.swift.org/browse/SR-4414

Generics型で重複した型の制約を書くとクラッシュする"場合がある"

https://github.com/tarunon/SR-4434
限定的な条件下でのみクラッシュしますが、重複した型の制約を外せば良いだけなので実務上影響は無いです。
しかし、クラッシュする箇所が重複した型の制約の箇所ではなく、他の場所でクラッシュするため見つけにくい。
不幸にもクラッシュしてしまった場合は重複した型の制約を探すと良いかもしれません。

報告済み
https://bugs.swift.org/browse/SR-4434

classでassociatedtypeをSelfに束縛できなくなった

http://qiita.com/tarunon/items/343ec5fcc059a144f2d1
↑死にました
元々Linux版ではクラッシュしていたようで、完全にコンパイラの虚を突いたworkaroundだったので仕方ない感はあります。
特に報告する必要もなさそうなのでしていません。