Swift3.0でコンパイル出来ない型n選
Xcode8、並びにSwift3.0がリリースされました。めでたい🎉
しかし、Swift2.2まではコンパイルに通っていたが、Swift3.0では通らなくなった型があります。
全体的にちゃんと調べてないので、それが仕様なのかバグなのかについては親切な人が教えてくれると思います。
制約付きassociatedtypeを束縛するGenerics関数
制約に他のprotoclを持つassociatedtypeを宣言したprotocolを2つ定義し、Generics関数でassociatedtype同士を束縛します。
protocol A {}
protocol B {
associatedtype X: A
}
protocol C {}
protocol D {
associatedtype Y: C
func hoge<Z: B>(v: Z) where Z.X == Y
}
Generics関数を持つprotocol (D) の具体型を実装すると、コンパイルが通らなくなります。
// 素直に実装してみる。🙅
class O<P: C>: D {
typealias Y = P
func hoge<Z: B>(v: Z) where Z.X == P {
}
}
// protocol extensionに実装を逃がしてみる。🙅
extension D {
func hoge<Z: B>(v: Z) where Z.X == Y {
}
}
class Q<R: C>: D {
typealias Y = R
}
workaround
Genericsの対象となるprotocolのassociatedtypeから束縛を外せば、コンパイルが通るようになります。
// everything is ok! 🎉
protocol A {}
protocol B {
associatedtype X //: A
}
protocol C {}
protocol D {
associatedtype Y: C
func hoge<Z: B>(v: Z) where Z.X == Y
}
class O<P: C>: D {
typealias Y = P
func hoge<Z: B>(v: Z) where Z.X == P {
}
}
extension D {
func hoge<Z: B>(v: Z) where Z.X == Y {
}
}
class Q<R: C>: D {
typealias Y = R
}
或いは、protocolから関数の宣言を取り除けばコンパイルが通るようになります。
protocol A {}
protocol B {
associatedtype X: A
}
protocol C {}
protocol D {
associatedtype Y: C
// func hoge<Z: B>(v: Z) where Z.X == Y
}
class O<P: C>: D {
typealias Y = P
func hoge<Z: B>(v: Z) where Z.X == P {
}
}
extension D {
func hoge<Z: B>(v: Z) where Z.X == Y {
}
}
class Q<R: C>: D {
typealias Y = R
}
protocol extensionに生やした関数を他の型で再実装した時の挙動を考えると、associatedtypeの制約をゆるくしたほうが安全だと思います。
ただ、B.X
の制約がないと困るケースが考えられますが、それについてはB
を拡張した別のprotocolで束縛して、そこから下にextensionで実装をぶら下げるしか無さそうです。
同じprotocolを制約に持つassociatedtype
ひとつ前のパターンの凶悪なやつです。workaroundが減ります。
この場合は、protocolにおける関数の宣言の有無に関わらず、Generics関数を持つ具体型が実装出来なくなります。
protocol A {}
protocol B {
associatedtype X: A
}
protocol C {
associatedtype Y: A
}
// 🙅
class O<P: C>: C {
typealias Y = P
func hoge<Z: B>(v: Z) where Z.X == P {
}
}
// 🙅
extension C {
func hoge<Z: B>(v: Z) where Z.X == Y {
}
}
class Q<R: C>: C {
typealias Y = R
}
// global func は 🙆
func hoge<S: B, T: C>(v1: S, v2: T) where S.X == T.Y {
}
workaround
この場合はassociatedtypeからprotocolを取り外す他にないでしょう。
associatedtypeの束縛は、宣言した大元のprotocolのサブセットに任せ、具体的な実装はglobal funcに持たせるしか無さそうです。とてもつらい
以下見つけ次第追記
Author And Source
この問題について(Swift3.0でコンパイル出来ない型n選), 我々は、より多くの情報をここで見つけました https://qiita.com/tarunon/items/61d936d178f11327f805著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .