Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More Powerful Constraints for Associated Types #284

Merged
merged 12 commits into from Sep 23, 2016
75 changes: 75 additions & 0 deletions proposals/XXXX-associated-types-constraints.md
@@ -0,0 +1,75 @@
# Permit where clauses to constrain associated types

* Proposal: [SE-XXXX](https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-associated-types-constraints.md)
* Author(s): [David Hart](http://github.com/hartbit), [Jacob Bandes-Storch](jtbandes@gmail.com), [Douglas Gregor](dgregor@apple.com)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those email address links don't work in Markdown. The template has also changed recently.

* Proposal: [SE-NNNN](NNNN-associated-types-constraints.md)
* Authors: [David Hart](https://github.com/hartbit), [Jacob Bandes-Storch](https://github.com/jtbandes), [Doug Gregor](https://github.com/DougGregor)
* Review Manager: TBD
* Status: **Awaiting review**

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

* Status: TBD
* Review manager: TBD

## Introduction

This proposal seeks to introduce a `where` clause to associated types declarations and improvements to protocol constraints to bring associated types the same expressive power as generic types.

This proposal was discussed twice on the Swift Evolution list in the following threads:

- [[Completing Generics] Arbitrary requirements in protocols](http://thread.gmane.org/gmane.comp.lang.swift.evolution/14243)
- [More Powerful Constraints for Associated Types](http://thread.gmane.org/gmane.comp.lang.swift.evolution/15201)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the Gmane web interface is back those links should be updated.

* [\[Completing Generics\] Arbitrary requirements in protocols](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/014667.html)
* [Proposal] More Powerful Constraints for Associated Types
  - [Week #1](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015625.html)
  - [Week #2](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160425/015753.html)
  - [Week #3](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016354.html)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will do that asap!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


## Motivation

Currently, associated type declarations can only express simple inheritance constraints and not the more sophisticated constraints available to generic types with the `where` clause. Some designs, including many in the Standard Library, require more powerful constraints for associated types to be truly elegant. For example, the `SequenceType` protocol can be declared as follows:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Please hard-wrap lines in markdown. Otherwise diffs start to become very hard to work with.
  2. s/can/could—if it were supported—/?

Copy link
Collaborator Author

@hartbit hartbit Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(2) Not entirely sure what you mean?


```swift
protocol Sequence {
associatedtype Iterator : IteratorProtocol
associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
...
}
```

## Detailed Design

First of all, this proposal modifies the grammar for protocols associated types to the following:

*protocol-associated-type-declaration* → *attributes<sub>opt</sub>* *access-level-modifier<sub>opt</sub>* **associatedtype** *typealias-name* ­*type-inheritance-clause­<sub>opt</sub>* *typealias-assignment­<sub>opt</sub>* *requirement-clause<sub>opt</sub>*

The new requirement-clause is then used by the compiler to validate the associated types of conforming types.

Secondly, the proposal also allows protocols to use the associated types of their conforming protocols in their declaration where clause as below:

```swift
protocol IntSequence : Sequence where Iterator.Element == Int {
...
}
```

Name lookup semantics in the protocol declaration `where` clause only looks at associated types in the parent protocols. For example, the following code would cause an error:

```swift
protocol IntSequence : Sequence where Counter: Int { // error: Use of undefined associated type 'Counter'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Counter: Int/Counter : SomeProtocol/?

Constraining counter to be Int exactly I think makes it a non-associated type, better modeled by a typealias in the protocol.

Copy link
Collaborator Author

@hartbit hartbit Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, understood.

associatedtype Counter
}
```

But instead should be written on the associated type itself:

```swift
protocol IntSequence : Sequence {
associatedtype Counter: Int
}
```

## Alternatives

Douglas Gregor argues that the proposed syntax is redundant when adding new constraints to an associated type declared in a parent protocol and proposes another syntax:

```swift
protocol Collection : Sequence {
where SubSequence : Collection
}
```

But as Douglas notes himself, that syntax will become ambiguous if we adopt the generic where clause at the end of declarations like discussed in proposal [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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since that proposal was adopted, you probably want to rewrite this section.


## Acknowledgements

Thanks to Dave Abrahams and Douglas Gregor for taking the time to help me through this proposal.