extension where T: SomeClass と where T == SomeClass の補完上の区別 & 原因求む

# TL;DR
下記の図をご覧ください
![スクリーンショット 2017-11-07 23.52.16.png](https://qiita-image-store.s3.amazonaws.com/0/63998/7438d153-758b-f397-1d51-72e7426957fe.png)
.
![スクリーンショット 2017-11-07 23.52.31.png](https://qiita-image-store.s3.amazonaws.com/0/63998/0fc68a14-cb96-b183-5cb9-9aa43cf08edd.png)


そうです、`:` を使った場合、制約が満たされてなかったら補完リストに出ませんが、`==` を使う時は制約が満たされてなくても補完リストに出ます（当然コンパイルエラーにはなりますが）。理由は不明。エロい人教えてください。

# 細かい話
拡張は Swift で非常に頻繁に使われる機能の一つですが、特定な状況を拡張したい、例えば `Array` の `Element` が `String` であるのみの時に使われる `joined(separator: String) -> String` 機能はこんな感じで定義されています：

```swift
extension Array where Element == String {
    public func joined(separator: String = default) -> String
}
```

このように、Swift では `extension` の後ろに `where A == B` と言うように制約をつけることができますが、`where` の書き方はここでは `==` を使いましたが、他に `:` を使うこともできます。同じように見えますが、意味として微妙に違います。`==` の場合は 「`B` である」ことを意味しますが、`:` の場合は「`B` と見なせる」場合を意味します。

そして、実はどんな状況でも両方使えるわけではありません、`==` のみ使える場合と、`:` のみ使える場合があります。具体的にはこんな感じです

| `B` の型  | `==` | `:` |
|:-----|-----|-----|
| `class` | ⭕️ | ⭕️ |
| `struct` | ⭕️ | ❌ |
| `protocol` | ❌ | ⭕️ |

ご覧のように、`==` と `:` が両方使えるのは `B` が `class` のみの時です。なぜかと言うとまさに上記のニュアンスの違いがあって、`B` が `class` の場合は「その `class` である」場合と、「その `class` のサブクラスである」時の区別がありますが、`struct` は継承の概念がないので「その `struct` である」場合だけしかないですし、逆に `protocol` の場合は `protocol` 自体は何か特定な型ではないので何かしらの型に落とし込む必要があるため、「その `protocol` である」ことは意味がないのです。

ちなみに、両方使える `class` の場合は上記通り、`==` を使う場合と `:` を使う場合は微妙に動きが違う時があります。それは `protocol` に対する `extension` で、`A` が `Self` の時：

```swift:PatternA
protocol Some {}
extension UIView: Some {}
extension Some where Self: UIView {
	func test() { print("works") }
}

UIView().test() //works
UIImageView().test() //works
```

```swift:PatternB
protocol Some {}
extension UIView: Some {}
extension Some where Self == UIView {
	func test() { print("test") }
}

UIView().test() //works
UIImageView().test() //error: 'UIImageView' is not convertible to 'UIView'
```

こうなる理由はとてもわかりやすいですね、`==` は `である` を意味します。そして `UIImageView` は `UIView` を継承しているであって `UIView` ではないのです。だから `:` を使うと `test()` は普通に通りますが `==` を使うと `test()` がエラーになります

ところが、`extension Array where Element == SomeClass` の場合は、なぜか `SomeClass` のサブクラスでも通ります。ちょっと不思議な気分です🤔

でもこれも気になるのですが、今日一番気になるのはやはり TL;DR に書いてある補完の問題ですね。なぜか `:` で書くとちゃんと補完は正しいものにしか出てこないのですが `==` で書くと適合していない場合でも補完に出ます。コンパイルエラーになるのに。

ちなみに、なぜこの挙動に気づいたかと言うと、自分で [NotAutoLayout](https://github.com/el-hoshino/NotAutoLayout) という ~~Auto Layout を殺す~~脱 Auto Layout のフレームワークを作っているのですが、中に[このように](https://github.com/el-hoshino/NotAutoLayout/blob/master/NotAutoLayout/NotAutoLayout/LayoutMakers/0PropertyDidSetMakers/InitialLayoutMaker.swift) `LayoutMaker` という型を作って、Phantom Type っぽい挙動で特定な場合には特定なヘルパーメソッドを作りたかったのですが、なぜか補完リストには条件が合わない時のメソッドもズラッと出てきて、非常に不親切だなぁと思ってそうならないように結局渋々すごいたくさんの `XxxLayoutMaker` 型を作りました。ところで今日 Phantom Type について[こに記事](https://qiita.com/taketo1024/items/71e3272211f08d7e0cde)を読んで、「あーでも `.shout()` は最初から補完リストに出るんだよなぁ」と思いながら Playground にソースコードコピペしたら出てこなかった！「ん？」って思って色々試してみた結果、その記事では `:` を使っているから補完リストが正しく動いたことが判明しました。

しかし、上の表にも書いてある通り、`struct` を使った場合はそもそも `:` が使えないので、`class` を使う必要があるんですよね…ところが `class` を作った場合、仮に `final` をつけたとしても、生成コストは `struct` より高いのであんまり使いたくない感 is ある…無限に `protocol` 生やすしかないのかな（白目