|
1 | 1 | # Using Protocols with `Self` or Associated Type Requirements
|
| 2 | + |
2 | 3 | Protocols in Swift may be used as types, as part of a generic constraint, or as part of an opaque result type.
|
3 | 4 |
|
4 | 5 | ```swift
|
5 |
| -// CustomStringConvertible can be used as a type. |
| 6 | +// `CustomStringConvertible` can be used as a type. |
6 | 7 | func foo(bar: CustomStringConvertible) { /* ... */ }
|
7 | 8 |
|
8 |
| -// ...or as a generic constraint on 'T'. |
| 9 | +// ...or as a generic constraint on `T`. |
9 | 10 | func bar<T: CustomStringConvertible>(baz: T) { /* ... */ }
|
10 | 11 |
|
11 | 12 | // ...or as part of an opaque result type.
|
12 | 13 | func baz() -> some CustomStringConvertible { /* ... */ }
|
13 | 14 | ```
|
14 | 15 |
|
15 |
| -While all Swift protocols can be used as generic constraints and as part of opaque result types, not all protocols can be used as types in general. Specifically, if a protocol has a requirement which references `Self` or an associated type, it cannot be used as a type. One such protocol is `Identifiable`, which has the requirement `var id: ID { get }`, where `ID` is an associated type. As a result, the following code is not allowed: |
| 16 | +While all Swift protocols can be used as generic constraints and as part of opaque result types, not all protocols can be used as types. Specifically, if a protocol has a requirement which references `Self` (in contexts other than a function's return type) or an associated type, it cannot be used as a type. For example, the protocol `Equatable` requires `static func == (lhs: Self, rhs: Self) -> Bool`, and the protocol `Identifiable` requires `var id: ID { get }`, where `ID` is an associated type. As a result, the following code is not allowed: |
16 | 17 |
|
17 | 18 | ```swift
|
| 19 | +func foo(bar: Equatable) { /* ... */ } |
| 20 | +// error: protocol 'Equatable' can only be used as a generic constraint because it has Self or associated type requirements |
| 21 | + |
18 | 22 | func foo(bar: Identifiable) { /* ... */ }
|
19 | 23 | // error: protocol 'Identifiable' can only be used as a generic constraint because it has Self or associated type requirements
|
20 | 24 | ```
|
21 | 25 |
|
22 |
| -Protocols like `Identifiable` which have `Self` or associated type requirements cannot be used as types because such types would rarely be useful in practice. They would be unable to allow use of `Self` or associated type requirements like `var id: ID { get }` because the associated type is not specified. |
| 26 | +These `Self` or associated type requirements cannot be used via a protocol type because they do not have a well-defined meaning without a concrete conforming type. Therefore, Swift does not support the use of protocols as types if they have such `Self` or associated type requirements, since those types would be able to present only a potentially unusable subset of the interface required for instances of concrete conforming types. |
23 | 27 |
|
24 |
| -When working with protocols having `Self` or associated type requirements constrained generics, opaque result types, or manual type erasure is sufficient to support most use cases. To learn more, see the [Protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [Generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [Opaque Types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) sections of _The Swift Programming Language_. |
| 28 | +When working with protocols that have `Self` or associated type requirements, most use cases can be supported by constrained generics, opaque result types, or manual type erasure. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in _The Swift Programming Language_. |
0 commit comments