Swift 5.1 に導入される Opaque Result Type とは何か

Swift 5.1 で **Opaque Result Type** ([SE-0244](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md)) が導入されます。

Opaque Result Type とは何でしょうか。例を見てみましょう。次のような `Animal` と `Cat` があるとします。

```swift
protocol Animal {
    func foo()
}

struct Cat: Animal {
    func foo() { print("cat") }
}
```

このとき、↓の `makeAnimal` の戻り値の型である `some Animal` のような型が Opaque Result Type です。

```swift
func makeAnimal() -> some Animal { // この `some` が新しい
    return Cat()
}

let animal = makeAnimal()
animal.foo() // "cat" と表示される
```

`some` という新しい言語機能を導入しなくても、 `-> some Animal` の代わりに `-> Cat` や `-> Animal` とすれば既存の言語機能で同じようなことが実現できます。しかし、

- **`-> Cat` では、内部実装を過剰に公開している**
- **`-> Animal` では、パフォーマンス上のロスが発生する**

という問題がありました。これを解決するために、 **内部実装を隠蔽しながらパフォーマンスにも影響しない手段として Opaque Result Type が提案されました。**

僕は、 **Opaque Result Type は Swift にとって重要な新機能** だと考えています。しかし、なかなかとらえどころのない概念で僕も理解するまでに少し時間がかかりました。そこで、他の言語機能と比較しながらより俯瞰的な視点を導入することで、 Opaque Result Type とは何かをわかりやすく説明したいと思います。

## 内部実装を過剰に公開するとはどういうことか

まずは↓の意味を、より現実的な例で説明します。

> `-> Cat` では、内部実装を過剰に公開している

今、二つの値を保持する `Pair` 型を作りたいとします。この `Pair` 型は同じ型の値を二つ持ち、 `Array` のように `for-in` ループで値を取り出せるものを想定しています。 `Pair` を使うコードと実行結果の例は次の通りです。

```swift
let pair: Pair<Int> = Pair(2, 3)
for value in pair {
    print(value)
}
```

```
2
3
```

`for-in` ループで値を取り出せるようにするには、 Swift では `Sequence` プロトコルに適合している必要があります。そのような `Pair` 型を実装する簡単な方法は、次のように `Array` をラップしてしまうことでしょう。

```swift
struct Pair<Value>: Sequence {
    private var array: [Value]

    init(_ value1: Value, _ value2: Value) {
        array = [value1, value2]
    }

    var values: (Value, Value) { return (array[0], array[1]) }

    func makeIterator() -> IndexingIterator<[Value]> {
        return array.makeIterator()
    }
}
```

上記のコード中で、 `makeIterator` の戻り値の型である `IndexingIterator<[Value]>` はあまり見慣れない型だと思います。

`Pair.makeIterator` の戻り値の型が `IndexingIterator<[Value]>` なのは、 `Array.makeIterator` に由来しています。 `Pair.makeIterator` は単に `array.makeIterator()` の結果を `return` するだけです。そのため、 `Pair` と `Array` の `makeIterator` の戻り値の型は同じものになります。ここでは、 `array.makeIterator()` の戻り値の型が `IndexingIterator<[Value]>` なので、そのまま `Pair.makeIterator` の戻り値の型も `IndexingIterator<[Value]>` としました。

**しかし、これは実装の詳細を不必要に露出してしまっています。**

たとえば、↑のコードでは `Array` をラップして `Pair` を実装していますが、より効率的[^1]な実装とするためにタプルを使って実装することにしてみましょう。

```swift
struct Pair<Value>: Sequence {
    private(set) var values: (Value, Value)

    init(_ value1: Value, _ value2: Value) {
        values = (value1, value2)
    }

    func makeIterator() -> /* ??? */ {
        /* ... */
    }
}
```

このとき、 `makeIterator` が返すイテレーターを自力で実装する必要があります。

```swift
enum PairIterator<Value>: IteratorProtocol {
    case first(Value, Value)
    case last(Value)
    case none

    mutating func next() -> Value? {
        switch self {
        case .first(let first, let last):
            self = .last(last)
            return first
        case .last(let last):
            self = .none
            return last
        case .none:
            return nil
        }
    }
}
```

これを使って `Pair` の `makeIterator` を実装すると次のようになります。

```swift
struct Pair<Value>: Sequence {
    /* ... */

    func makeIterator() -> PairIterator<Value> {
        return .first(values.0, values.1)
    }
}
```

最初の実装では `makeIterator` の戻り値の型は `IndexingIterator<[Value]>` でしたが、新しい実装では `PairIterator<Value>` になりました。 **これは、カプセル化された内部実装を変更したかっただけなのに、公開された API の型が変更されてしまったことを意味します。**

加えて、新しい実装では `PairIterator` を作りましたが、もしかすると `Pair` の実装をさらに変更してやっぱり `PairIterator` が不要になるかもしれません。 `PairIterator` を返すことは、 **将来的に不要になるかもしれない型を公開していることにもなります。** 今やりたいことは、 `Value` を取り出せる何らかのイテレーターインスタンスを返したいということだけです。そのために `PairIterator` という型を露出してしまうのは過剰です。可能であれば `PairIterator` は `private` な型にしておきたいところです。

これが、「内部実装を過剰に公開している」ということです。

## なぜプロトコル型にパフォーマンス上のロスがあるのか

次に、↓のロスがなぜ発生するのかについて説明します。

> `-> Animal` では、パフォーマンス上のロスが発生する

`Animal` はプロトコルなので、この関数はプロトコル型の値を返すことになります。 Swift ではプロトコル型は Existential Type とも呼ばれます[^2]。 Existential Type には実行時のオーバーヘッドがあり、 Swift の標準ライブラリでは Existential Type はほとんど使われていません（ `AnySequence` などの Type Erasure や `Any` を除く）。

Existential Type は一見して感じられるよりも多くのことを裏で行っています。たとえば、次のようなコードを考えてみましょう。

```swift
var animal: Animal = Cat()
animal = Dog()
```

`animal` は `Animal` 型の変数なので、 `Cat` と `Dog` の両方が代入できても何もおかしなことはないように感じられるかもしれません。しかし、 `Cat` と `Dog` の実装が次のようになっているとどうでしょうか。

```swift
struct Cat: Animal {
    var a: UInt8 = 42
}
struct Dog: Animal {
    var b: Int64 = -1
}
```

この場合、 `Cat` を変数／定数に格納するには 1 バイト、 `Dog` を格納するには 8 バイトの領域を必要とします。

```swift
let cat: Cat = Cat()
MemoryLayout.size(ofValue: cat) // 1

let dog: Dog = Dog()
MemoryLayout.size(ofValue: dog) // 8
```

では、この両方を格納できる `Animal` 型の変数／定数には何バイトの領域が必要でしょうか？

```swift
var animal: Animal = Cat()
MemoryLayout.size(ofValue: animal) // 40
```

なんと 40 バイトもの領域が必要になりました。これは、 `Animal` に適合したどのような型のインスタンスでも格納できるように、 Existential Container という入れ物に包まれているからです[^3]。

**Existential Type を使うと、引数に渡すときに Existential Container に包むオーバーヘッドが発生し、メソッドを呼ぶときには Existential Container を開いて間接的にメソッドを呼び出すオーバーヘッドが発生します。**

```swift
func useAnimal(_ animal: Animal) {
    animal.foo() // ここで Existential Container を開くオーバーヘッド発生
}

let cat = Cat()
useAnimal(cat) // ここで Existential Container に包むオーバーヘッド発生
```

このように、 Existential Type を使うとパフォーマンス上のロスが発生します。

## Existential Type のオーバーヘッドをジェネリクスで解決する

Existential Type とジェネリクスの役割は異なりますが、どちらでもできることもあります。たとえば、次のどちらの書き方でも同じような関数を実装することができます。

```swift
// Existential Type
func useAnimal(_ animal: Animal) { animal.foo() }

// ジェネリクス
func useAnimal<A: Animal>(_ animal: A) { animal.foo() }
```

しかし、これらの実行時のパフォーマンスは異なります。

`useAnimal` を実装するときに、パフォーマンス的に最良なのは個別の型について書き下すことです。

```swift
func useAnimal(_ animal: Cat) { animal.foo() }
func useAnimal(_ animal: Dog) { animal.foo() }
// その他のすべての `Animal` に適合した型についての実装が続く
```

そうすると、コンパイル時に `animal` の型が確定するので、 `animal.foo()` で呼ばれるメソッドの実体をコンパイル時に確定させることができます（ `Cat` や `Dog` がクラスで `final` でない場合はその限りではありませんが、ここでは `Cat` や `Dog` は値型であると仮定します）。 Existential Container を開いて間接的にメソッドを呼び出すようなオーバーヘッドは存在しません。しかし、現実には `Animal` に適合した型は無限に存在し得ますし、上記のような似たコードの繰り返しは望ましくありません。

ジェネリクスはこのようなオーバーロードをまとめて書くものだと考えるとわかりやすいです[^4]。

```swift
func useAnimal<A: Animal>(_ animal: A) { animal.foo() }
```

Swift では、 Specialization という最適化が行われた場合、↑のジェネリクスで書かれた `useAnimal` は、個別の型に対して書かれた `useAnimal` と同等のパフォーマンスを実現することができます。 Specialization が行われると、型パラメータに対して具体的な型を埋めたもの（上記の例では `A` に `Cat` や `Dog` を埋めたもの）がコンパイル時に生成されます[^5]。 `useAnimal(Cat())` はまるで `func useAnimal(_ animal: Cat)` が存在するかのように振る舞います。 **Specialization が行われた場合、ジェネリクスには Existential Type と違って実行時のオーバーヘッドがありません。**

ジェネリクスと Existential Type は共に抽象的な型に対してコードを書くための手段を提供しますが、ジェネリクスには実行時のオーバーヘッドがないという利点があります。一般的には、ジェネリクスと Existential Type でできることは異なり、適切に使い分けられるべきです。しかし、どちらでもできることもあり、そのような場合はジェネリクスが好ましい場合が多いでしょう。

## 『リバースジェネリクス』

ジェネリクスを使えば Existential Type の問題を解決できるケースがあることを見ました。しかし、それは引数の話でした。

```swift
// Existential Type
func useAnimal(_ animal: Animal) { animal.foo() }

// ジェネリクス
func useAnimal<A: Animal>(_ animal: A) { animal.foo() }
```

Existential Type を返す次のような関数に対して、同じ様にパフォーマンスの問題を解決するにはどうすれば良いでしょうか？

```swift
// Existential Type
func makeAnimal() -> Animal {
    return Cat()
}
```

ジェネリクスではうまくいきません。

```swift
// ジェネリクス
func makeAnimal<A: Animal>() -> A {
    return Cat() // コンパイルエラー
}
```

ジェネリクスの型パラメータを決めるのはその API の利用者です。にも関わらず↑のコードは `makeAnimal` の実装自体が `A` を `Cat` と仮定してしまっています。戻り値のジェネリクスは Swift でサポートされていますが、上記のコードは利用者ではなく実装者が型を決定しようとしているので型エラーでコンパイルに失敗します。

今やりたいのは、 `-> Cat` とした場合と同じパフォーマンスを実現しながら、 `-> Animal` とした場合と同じように具体的な型を隠蔽したいということです。そのためには、ジェネリクスとは異なる概念が必要になります。

Swift Forums で、 [&#64;orobio](https://forums.swift.org/u/orobio/) さんがそのような概念を『リバースジェネリクス』と名付けて説明しています[^6]。ここでは、 [&#64;orobio](https://forums.swift.org/u/orobio/) さんの記法の代わりに、 Swift Core Team の Joe Groff が言及している記法[^7]を採用してこの『リバースジェネリクス』を考えてみます。

ジェネリクスを用いて `useAnimal` を引数の型を抽象的に記述するのに対して、『リバースジェネリクス』を用いて `makeAnimal` の戻り値の型を抽象的に記述しようとすると次のようになります。

```swift
// ジェネリクス
func useAnimal<A: Animal>(_ animal: A) {
    animal.foo()
}

// 『リバースジェネリクス』
func makeAnimal() -> <A: Animal> A {
    return Cat()
}
```

これらを比較すると次のような裏返し（双対）の関係にあります。

- `useAnimal` の **利用者** が `A` の具体的な型を定め、 `useAnimal` の **実装者** は抽象的な `A` に対してコードを書く。
- `makeAnimal` の **実装者** が `A` の具体的な型を定め、 `makeAnimal` の **利用者** は抽象的な `A` に対してコードを書く。

`makeAnimal` を使うコードの例は↓です。

```swift
let animal = makeAnimal()
animal.foo()
```

`makeAnimal` で返されるのは実際には `Cat` インスタンスですが、 `makeAnimal` の利用者にはそれは見えません。あくまで `Animal` に適合した何らかの型のインスタンスが返されたものとして扱います。しかし、実際にはそれは `Cat` なのでコンパイラが Specialization を行い、 `makeAnimal` が `Cat` を返すのと同じパフォーマンスを発揮することができるわけです。

上記のコードでは `animal` の型を明記していませんが、型推論を使わずに明示的に記述しようとするとどうなるでしょうか。そのような記法は存在しませんが、概念的には次のように書けます。

```swift
let animal: makeAnimal.A = makeAnimal()
animal.foo()
```

`makeAnimal.A` とは、 `makeAnimal` が返す `Animal` に適合した `A` 型という意味です。 `makeAnimal.A` は実際には `Cat` ですが、そのことは利用者には隠蔽されているので次のようなコードは型エラーとなります。

```swift
let animal = makeAnimal()
let cat: Cat = animal // コンパイルエラー
```

これは、↓ができないのと似ています。

```swift
func useAnimal<A: Animal>(_ animal: A) {
    let cat: Cat = animal // コンパイルエラー
    cat.foo()
}
```

また、 `makeAnimal.A` を通して（ `Animal` には宣言されてない） `Cat` 独自のプロパティやメソッドを呼び出すこともできません。

このように、 **ジェネリクスの対となる『リバースジェネリクス』という概念を導入すれば、具体的な型を隠蔽したまま実行時のオーバーヘッドを支払わずに済ませられます。** `-> Cat` と `-> Animal` のいいとこ取りができるわけです。

## シンタックスシュガーとしての Opaque Type

とらえどころのない Opaque Result Type ですが、『リバースジェネリクス』という概念を導入すると、 **Opaque Result Type は『リバースジェネリクス』のシンタックスシュガーである** とシンプルに考えることができます。 つまり、次の二つが等価だということです。

```swift
// 『リバースジェネリクス』
func makeAnimal() -> <A: Animal> A {
    return Cat()
}

// Opaque Result Type
func makeAnimal() -> some Animal {
    return Cat()
}
```

同様に、ジェネリック引数のシンタックスシュガーとして、 Opaque Argument Type も提案されています。今回のプロポーザル（ SE-0244 ）が Accept されてもそこで実装される範囲には含まれていませんが、プロポーザルの Future Directions で言及されています[^8]。

```swift
// ジェネリクス
func useAnimal<A: Animal>(_ animal: A) {
    animal.foo()
}

// Opaque Argument Type
func useAnimal(_ animal: some Animal) {
    animal.foo()
}
```

 Opaque Argument Type と Opaque Result Type をジェネリクスと『リバースジェネリクス』のシンタックスシュガーと考えると、とらえどころのない概念を自然なものとして受け入れることができるのではないでしょうか。

## Opaque Result Type の挙動

Opaque Result Type の挙動についてはわかりづらい点もあるので、いくつか例を挙げてみます。

```swift
func makeAnimal() -> some Animal {
    return Cat()
}

var animal1 = makeAnimal()
let animal2 = makeAnimal()
animal1 = animal2 // OK
```

↑は当然 OK です。しかし、

```swift
func makeAnimal1() -> some Animal {
    return Cat()
}

func makeAnimal2() -> some Animal {
    return Cat()
}

var animal1 = makeAnimal1()
let animal2 = makeAnimal2()
animal1 = animal2 // コンパイルエラー
```

↑は、同じ `some Animal` 同士で、その実体はどちらも `Cat` なのにコンパイルエラーになりました。異なる API から返された Opaque Result Type は、その実体が同じものであっても別の型とみなされます。そうでなければ、後から `makeAnimal2` が `Dog` を返すように内部実装が変更されたときに、 API の型は変わらないのに型チェックの挙動が変わってしまうことになります。

```swift
func makeAnimal1() -> some Animal {
    return Cat()
}

func makeAnimal2() -> some Animal {
    return Dog()
}

var animal1 = makeAnimal1()
let animal2 = makeAnimal2()
animal1 = animal2 // これは当然コンパイルエラーにしないといけない
```

また、次のように、一つの API で複数の `some Animal` が書かれた場合でも、それらは別の型とみなされます[^9]。

```swift
func makeAnimals() -> (some Animal, some Animal) {
    return (Cat(), Cat())
}

var (animal1, animal2) = makeAnimals()
animal1 = animal2 // コンパイルエラー
```

これも後から `return (Cat(), Dog())` に内部実装が変更されても、利用側で型チェックの挙動が変わらないためには必須です。なお、このケースは『リバースジェネリクス』を用いて次のように考えると理解しやすいです。

```swift
func makeAnimals() -> <A: Animal, B: Animal> (A, B) {
    return (Cat(), Cat())
}

var (animal1, animal2) = makeAnimals()
animal1 = animal2 // `A` と `B` は異なるのでコンパイルエラー
```

同じ字面の `some Animal` 同士で代入できないことには違和感を感じる人もいるかもしれませんが、 "some" （ある） `Animal` だと考えると、「ある `Animal`」と「ある `Animal`」が異なるものであることは言語的に自然です。そういう意味で、 `some` というキーワードは秀逸だと思います。

**（追記 2019-05-02）** Opaque Result Type はすでに実装されマージされているので、現時点でも [Swift 5.1 のスナップショット](https://swift.org/download/#snapshots)をダウンロードして Opaque Result Type を試すことができます。

## `Pair` を Opaque Result Type で実現する

前述の `Pair.makeIterator` の戻り値の型は `PairIterator<Value>` という具体的な型になっており、 `makeAnimal` の戻り値を `-> Cat` で記述するのと同じ状態でした。

```swift
struct Pair<Value>: Sequence {
    /* ... */

    func makeIterator() -> PairIterator<Value> {
        return .first(values.0, values.1)
    }
}
```

これを Opaque Result Type で記述するとどうなるでしょうか。

`makeIterator` は単に `IteratorProtocol` に適合した型の値を返すというだけでなく、その `Element` の型が `Value` である必要があります。 Opaque Result Type でそのような制約を記述できる記法が必要です。

プロポーザル（ SE-0244 ）には、 Future Directions としてそのような制約の記述の記法についての言及があります。そこで書かれている記法の一つを使うと、次のように書くことができます。

```swift
struct Pair<Value>: Sequence {
    /* ... */

    func makeIterator() -> some IteratorProtocol<.Element == Value> {
        return PairIterator.first(values.0, values.1)
    }
}
```

これは、『リバースジェネリクス』を使って次のように書くのと等価です。

```swift
struct Pair<Value>: Sequence {
    /* ... */

    func makeIterator() -> <I: IteratorProtocol> I where I.Element == Value {
        return PairIterator.first(values.0, values.1)
    }
}
```

もしくは、 `<.Element == Value>` の記法が `where` 節の短縮記法としてジェネリクスや『リバースジェネリクス』でも用いることができるなら次のようにも書けるでしょう。

```swift
// 『リバースジェネリクス』
struct Pair<Value>: Sequence {
    /* ... */

    func makeIterator() -> <I: IteratorProtocol<.Element == Value>> I {
        return PairIterator.first(values.0, values.1)
    }
}
```

このとき、 `makeIterator` が返すイテレータは `PairIterator<Value>` インスタンスですが、 `makeIterator` はその型を露出しません。後から内部実装が変わって別のイテレータを返すようになっても、利用側のコードを修正する必要はないでしょう。また、 `PairIterator` 型も外部に公開する必要はなく、 `private` にできます。また、 Specialization が行われれば、 `makeIterator` の戻り値の型が `PairIterator<Value>` のときと同じパフォーマンスを得ることができます。

このように、 Opaque Result Type または『リバースジェネリクス』を用いることによって、具体的な型の隠蔽とパフォーマンスを両立できました。

## ジェネリクスと Existential Type でできることの違い

ここからはやや余談となりますが、 Opaque Result Type の位置付けを探るために関連の言語機能を深掘りしてみます。

本投稿では主にパフォーマンスに着目してジェネリクスの Existential Type に対する優位性を説明しました。しかし、ジェネリクスと Existential Type で表現できることには違いがあり、代替するものではなく互いに補完する存在です。ケース・バイ・ケースで適切に使い分けることが大切です。

ここでは、ジェネリクスでしかできないこと、 Existential Type でしかできないことを見てみます。

### ジェネリクスでしかできないこと

単体テストでよく使うような `assertEquals` 関数を実装することを考えてみましょう。

```swift
assertEquals(a, 42) // `a` が `42` になっているか検査する
```

二つの値を比較して等しいかを検査するためには、その値を比較する手段がなければなりません。 Swift では、 `Equatable` プロトコルに適合している値は `==` で比較することができます。

この `assertEquals` は Existential Type では書けません。無理やり書こうとすると次のようになってしまいます。

```swift
// Existential Type
func assertEquals(_ actual: Equatable, _ expected: Equatable) {
    /* ... */
}
```

`Equatable` は `Self` 引数を持つメソッドを持つので、そもそも Existential Type である `Equatable` 型の引数を作ることはできませんが、ここでは仮にできるものとしてみましょう。

しかし、それでも `assertEquals` の引数の型を `Equatable` とするだけでは制約が不十分です。例えば、次のようなコードでもコンパイルを通ってしまいます。

```swift
assertEquals(42, "XYZ") // コンパイル可
```

第一引数の型は `Int` 、第二引数の型は `String` です。 `Equatable` は `Self` 同士の比較をするので、異なる型の間の比較は定義されていません。 `assertEquals` の二つの引数に異なる型の値を渡すのは明確なミスなので、コンパイルエラーになってほしいところです。しかし、 Existential Type ではそのような制約を記述することができません。

ジェネリクスを使えば `assertEquals` は次のように記述できます。

```swift
// ジェネリクス
func assertEquals<T: Equatable>(_ actual: T, _ expected: T) {
    /* ... */
}
```

この場合、 `actual` と `expected` は同じ型 `T` であることが強制されているので、 Existential Type では通ってしまった次のコードをコンパイルエラーにすることができます。

```swift
assertEquals(42, "XYZ") // コンパイルエラー
```

### Existential Type でしかできないこと

Existential Type にできてジェネリクスにできないこともあります。 Existential Type を使った次のコードは正しく実行することができます。

```swift
// Existential Type
func useAnimals(_ animals: [Animal]) {
    /* ... */
}

useAnimals([Cat(), Dog()]) // OK
```

しかし、ジェネリクスではできません。

```swift
func useAnimals<A: Animal>(_ animals: [A]) {
    /* ... */
}

useAnimals([Cat(), Dog()]) // コンパイルエラー
```

型パラメータ `A` は何か一つの具体的な型である必要があります。 `Cat` と `Dog` の両方になることはできません。

このように、 **Existential Type とジェネリクスはどちらが優れているというわけではなく、それぞれ異なる特性と表現力を持っており、適切に使い分けることが重要です。**

## Generalized Existential

Existential Type とジェネリクスは適切に使い分けるべきものだということでした。ここで、 `Pair.makeIterator` が Existential Type を返すようにしたらどうなるかを考えてみましょう。

ただし、 Swift 5.0 時点では実際に `Pair.makeIterator` が Existential Type を返すことはできません。 `Pair.makeIterator` が Existential Type を返すためには次の三つをクリアする必要があります。

1. `associatedtype` を持つプロトコル型の変数や引数を作ることは認められていない
2. プロトコル型はそのプロトコル自体に適合しない[^10]
3. `Pair.makeIterator` は `Element` が `Value` である `IteratorProtocol` を返す必要があるので、その制約を記述しなければならない

1 と 2 はサポートされたものと仮定して、 3 の記法を考えます。前述の Opaque Result Type では `some IteratorProtocol<.Element == Value>` という記法を用いました。この制約の記法を Existential Type にも採用することにしましょう。そうすると、 `Pair.makeIterator` が Existential Type を返す場合のコードを次のように書くことができます。

```swift
struct Pair<Value>: Sequence {
    /* ... */

    func makeIterator() -> IteratorProtocol<.Element == Value> {
        return PairIterator.first(values.0, values.1)
    }
}
```

このような、 Existential Type に対して制約を記述するための構文は Generalized Existential として議論されています[^11]。

なお、↑の `IteratorProtocol<.Element == Value>` の記法ついては、僕が説明のために勝手に考えたものではなく、プロポーザル（ SE-0244 ）の中でも次のように言及されており、 Generalized Existential での利用も見越されているようです（ただし、現時点では候補の一つに過ぎません）。

> This could be a generally useful shorthand syntax for declaring a protocol constraint with associated type constraints, usable in where clauses, some clauses, and generalized existentials
>
> 参考訳: これ（訳注: `<.Element == Value>` のような制約の記法）は `where` 節や `some` 節、 generalized existential で用いることができる、 associated type の制約を伴うプロトコル制約を宣言するための、広く役立つ簡略表現の構文になるかもしれない。

## `some` と `any`

このプロポーザル（ SE-0244 ）のレビューのスレッドの中で、 [Swift Core Team の Joe Groff がとても興味深いことを言っています](https://forums.swift.org/t/se-0244-opaque-result-types/21252/69)。

> Rust eventually decided that making existentials undecorated was a bad idea and added the `dyn` keyword to encourage their use to be explicit. In previous discussions of existential syntax, `Any` or `any` seemed like the clear favorite as the modifier keyword for explicitly introducing an existential. Both linguistically, and in the spirit of fairness of not syntactically biasing one style over the other, `Some` or `some` strikes me as the corresponding modifier for specific opaque types.
>
> 参考訳: Rust はついに existential を修飾なしの状態にするのは悪い考えであり、それら（訳注: Existential Type ）の利用が明示的であることを奨励するために `dyn` キーワードを追加することを決めた（訳注: Existential Type を `Aniaml` のように書くのではなく、 `dyn Animal` のように Existential Type であることを明示的に示すキーワードの付与を必要とする構文を採用した）。以前の existential の（訳注: Swift の）構文についての議論の中で、 `Any` や `any` は明示的に existential を導入するための修飾子のキーワードとして明確な有力候補だったように思う。言語的にも、そして、あるスタイルを別のスタイルに対して構文上ひいきしないという公平の精神の元でも（訳注: Existential Type と Opaque Type のどちらかを構文上書きやすくして、そちらを優先的に使うことを奨励しないために）、 `Some` や `some` は opaque type のための対応する修飾子だと私に思わせる。

この発言は、現在は Swift では `Animal` 型を単に `Animal` と書けるけれども、 `any Animal` のように明示的に Existential Type であることを示す修飾子を付けないといけないような構文も検討していることをうかがわせます。

```swift
// Existential Type
let animal: any Animal = Cat()
```

僕は以前から Swift で Existential Type が濫用されることを懸念していたので[^12]、もし Existential Type が明示的に `any` というキーワードを必要とするようになるなら、それは素晴らしい変更だと思います。

そして、もし `some` と `any` の両方が導入されたなら、次のような美しい対応を持つ構文が実現されます。

```swift
// ジェネリクス
func useAnimal<A: Animal>(_ animal: A) { /* ... */ }
// Opaque Argument Type （↑のシンタックスシュガー）
func useAnimal(_ animal: some Animal) { /* ... */ }
// Existential (Argument) Type
func useAnimal(_ animal: any Animal) { /* ... */ }

// 『リバースジェネリクス』
func makeAnimal() -> <A: Animal> A { /* ... */ }
// Opaque Result Type （↑のシンタックスシュガー）
func makeAnimal() -> some Animal { /* ... */ }
// Existential (Argument) Type
func makeAnimal() -> any Animal { /* ... */ }

// 制約付きの Opaque Type
let sequence: some Sequence<.Element == Int> = [2, 3, 5]
// Generalized Existential
let sequence: any Sequence<.Element == Int> = [2, 3, 5]
```

このように考えると Opaque Result Type はよくわからない新しい概念ではなく、 Swift がこれまで欠いていた当然追加されるべきピースの一つにすら見えてきます。

## その後の動向

**（追記 2019-03-26）** [レビューの結果](https://forums.swift.org/t/returned-for-revision-se-0244-opaque-result-types/22115)が出ました。その結果、 Opaque Result Type 単体としてよりも、 Generalized Existential 等との関係性や Future Directions に示されたような一連の変更を整理して示してから再レビューという流れになったようです。元のプロポーザルの中には Swift 5.1 の記載があったのですが、 Swift 5.1 に間に合うかは怪しくなってきました。個人的には、 Swift はすでにジェネリクスを持っているので（ Opaque Result Type と比べて）より汎用的な『リバースジェネリクス』をまずは導入し、その後、シンタックスシュガーとして Opaque Result Type が導入される流れになるのがいいんじゃないかと思ってます。

**（追記 2019-04-11）** Core Team から Opaque Result Types を含む包括的な方向性を説明する[ドキュメント](https://forums.swift.org/t/improving-the-ui-of-generics/22814)が公開されました。これは議論のために概念を説明するもので、方針が決定したわけではありません。また、それを受けて Opaque Result Type の[再レビュー](https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942)が開始されました。思ったより早かったので、 Swift 5.1 に間に合うかもしれません。

**（追記 2019-04-18）** Opaque Result Type の[再レビュー](https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942)が終わって[即 accept](https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942/58) されました。 [Swift 5.1 の final branching は終わってしまっている](https://swift.org/blog/5-1-release-process/)ので重要機能として特別に取り込まれない限りは Swift 5.2 か Swift 6.0 で利用可能になると思われます。

**（追記 2019-05-02）** Opaque Result Type の PR が Swift 5.1 のブランチにマージされ、 Swift 5.1 に導入されることが確定しました。また、[スナップショットが公開された](https://swift.org/download/#snapshots)ため、ダウンロードして Opaque Result Type を試すことができるようになりました。

[^1]: パフォーマンスとメモリ効率の両方の面で、タプルを使った実装の方が優れています。
[^2]: Swift のプロトコル型がどのように Existential Type であるのかについては @ukitaka さんの ["型システムの理論からみるSwiftの存在型(Existential Type)"](https://qiita.com/ukitaka/items/a993b5d7ed5ae84b1b52) を御覧ください。
[^3]: Existential Container についての詳しい説明は本題から外れてしまうのでここでは省略します。[わいわいswiftc #5 でもう少し詳しく話した](https://www.youtube.com/watch?v=hLYFiza-q94)のでそちらを御覧ください。
[^4]: 厳密にはオーバーロードと異なる挙動をするケースがあります。
[^5]: デフォルトでは同一モジュール内でしか Specialization は行われませんが、 `@inlinable` ([SE-0193](https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md)) を用いることでクロスモジュールでも Specialization を働かせることができます。
[^6]: [Reverse generics and opaque result types - Swift Forums](https://forums.swift.org/t/reverse-generics-and-opaque-result-types/21608)
[^7]: [SE-0244: Opaque Result Types - Swift Forums](https://forums.swift.org/t/se-0244-opaque-result-types/21252/69)
[^8]: [Opaque argument types - SE-0244 Opaque Result Types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md#opaque-argument-types)
[^9]: ただし、[タプルの値に Opaque Result Type を用いるのは Future Directions の一つ](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md#opaque-types-in-structural-position)であり、このプロポーザルが採用されても Swift 5.1 でできるようにはならないと思われます。
[^10]: これは、たとえば `func useAnimal<A: Animal>(_ animal: A)` に対して、 `let animal: Animal = Cat()` とした `animal` を `useAnimal(animal)` のように渡せないことを意味します。プロトコル型がそのプロトコル自体に適合することを self conformance と言いますが、 self conformance が実現されていない理由は[こちら](https://stackoverflow.com/a/43408193)で詳しく説明されています。
[^11]: [Generalized existentials - GenericsManifesto](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials)
[^12]: [なぜSwiftのプロトコルはジェネリクスをサポートしないのか](https://qiita.com/koher/items/b21879a31210f7408502)