|
| 1 | +# Permit where clauses to constrain associated types |
| 2 | + |
| 3 | +* Proposal: [SE-NNNN](NNNN-associated-types-constraints.md) |
| 4 | +* Authors: [David Hart](https://github.com/hartbit), [Jacob Bandes-Storch](https://github.com/jtbandes), [Doug Gregor](https://github.com/DougGregor) |
| 5 | +* Review Manager: TBD |
| 6 | +* Status: **Awaiting review** |
| 7 | + |
| 8 | +## Introduction |
| 9 | + |
| 10 | +This proposal seeks to introduce a `where` clause to associated type |
| 11 | +declarations and improvements to protocol constraints to bring associated types |
| 12 | +the same expressive power as generic type parameters. |
| 13 | + |
| 14 | +This proposal was discussed twice on the Swift Evolution list in the following |
| 15 | +threads: |
| 16 | + |
| 17 | +* [\[Completing Generics\] Arbitrary requirements in protocols](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/014667.html) |
| 18 | +* [Proposal] More Powerful Constraints for Associated Types |
| 19 | + - [Week #1](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015625.html) |
| 20 | + - [Week #2](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160425/015753.html) |
| 21 | + - [Week #3](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016354.html) |
| 22 | + |
| 23 | +## Motivation |
| 24 | + |
| 25 | +Currently, associated type declarations can only express simple inheritance |
| 26 | +constraints and not the more sophisticated constraints available to generic |
| 27 | +types with the `where` clause. Some designs, including many in the Standard |
| 28 | +Library, require more powerful constraints for associated types to be truly |
| 29 | +elegant. For example, the `SequenceType` protocol could be declared as follows |
| 30 | +if the current proposal was accepted: |
| 31 | + |
| 32 | +```swift |
| 33 | +protocol Sequence { |
| 34 | + associatedtype Iterator : IteratorProtocol |
| 35 | + associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element |
| 36 | + ... |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +## Detailed Design |
| 41 | + |
| 42 | +First of all, this proposal modifies the grammar for a protocol's associated types |
| 43 | +to the following: |
| 44 | + |
| 45 | +*protocol-associated-type-declaration* → |
| 46 | + *attributes<sub>opt</sub>* |
| 47 | + *access-level-modifier<sub>opt</sub>* |
| 48 | + **associatedtype** |
| 49 | + *typealias-name* |
| 50 | + *type-inheritance-clause<sub>opt</sub>* |
| 51 | + *typealias-assignment<sub>opt</sub>* |
| 52 | + *requirement-clause<sub>opt</sub>* |
| 53 | + |
| 54 | +The new requirement-clause is then used by the compiler to validate the |
| 55 | +associated types of conforming types. |
| 56 | + |
| 57 | +Secondly, the proposal also allows protocols to use the associated types of |
| 58 | +their conforming protocols in their declaration `where` clause as below: |
| 59 | + |
| 60 | +```swift |
| 61 | +protocol IntSequence : Sequence where Iterator.Element == Int { |
| 62 | + ... |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +Name lookup semantics in the protocol declaration `where` clause only looks at |
| 67 | +associated types in the parent protocols. For example, the following code would |
| 68 | +cause an error: |
| 69 | + |
| 70 | +```swift |
| 71 | +protocol SomeSequence : Sequence where Counter : SomeProtocol { // error: Use of undefined associated type 'Counter' |
| 72 | + associatedtype Counter |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | +But instead should be written on the associated type itself: |
| 77 | + |
| 78 | +```swift |
| 79 | +protocol IntSequence : Sequence { |
| 80 | + associatedtype Counter : SomeProtocol |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +## Effect on ABI Stability |
| 85 | + |
| 86 | +As mentioned previously, there are a number of places in the standard library where this feature would be adopted (such as the `SubSequence.Iterator.Element == Iterator.Element` example), each of which will change the mangling of any generic function/type that makes use of them. |
| 87 | + |
| 88 | +## Alternatives |
| 89 | + |
| 90 | +Douglas Gregor argues that the proposed syntax is redundant when adding new |
| 91 | +constraints to an associated type declared in a parent protocol and proposes |
| 92 | +another syntax: |
| 93 | + |
| 94 | +```swift |
| 95 | +protocol Collection : Sequence { |
| 96 | + where SubSequence : Collection |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +But as Douglas notes himself, that syntax is ambiguous since we adopted the |
| 101 | +generic `where` clause at the end of declarations of the following proposal: |
| 102 | +[SE-0081: Move where clause to end of declaration](https://github.com/apple/swift-evolution/blob/master/proposals/0081-move-where-expression.md). For those reasons, it might be wiser not to introduce the shorthand syntax. |
| 103 | + |
| 104 | +## Acknowledgements |
| 105 | + |
| 106 | +Thanks to Dave Abrahams and Douglas Gregor for taking the time to help me |
| 107 | +through this proposal. |
0 commit comments