[swift-evolution] [Pitch] Remove type inference for associated types

Douglas Gregor dgregor at apple.com
Wed Jun 29 00:33:29 CDT 2016

> On Jun 24, 2016, at 10:50 PM, Austin Zheng via swift-evolution <swift-evolution at swift.org> wrote:
> Hello all,
> Per Chris Lattner's list of open Swift 3 design topics (http://article.gmane.org/gmane.comp.lang.swift.evolution/21369 <http://article.gmane.org/gmane.comp.lang.swift.evolution/21369>), I've put together a proposal for removing type inference for associated types.
> It can be found here: https://github.com/austinzheng/swift-evolution/blob/az-assoctypeinf/proposals/XXXX-remove-assoctype-inference.md <https://github.com/austinzheng/swift-evolution/blob/az-assoctypeinf/proposals/XXXX-remove-assoctype-inference.md>
> Thoughts, criticism, and feedback welcome. There are at least two slightly different designs in the proposal, and I'm sure people will have ideas for even more.

Thanks for working on this. I have a couple of comments.

I don’t think we should be adding the ability to write ‘associatedtype’ declarations in classes/structs/enums. We already have the ability to explicitly state the associated type witness by declaring a typealias, struct, enum, or class with the appropriate name. Indeed, I feel like a lot of complexity of the proposal is linked to adding  ‘associatedtype’ declarations into the language, and I’d rather this proposal stay narrow.

I think it’s important for this proposal to show the other ways in which one can get associated type witnesses without writing them explicitly in the conforming type, even once inference goes away. For example, we have associated type defaults, e.g.,

	protocol P {
	  associatedtype Associated = Int

	struct X : P {
	  // Associated becomes Int if not otherwise specified

and with typealiases in protocol extensions becoming real and useful, one could also use protocol extensions:

	protocol P2 {
	  associatedtype Index

	extension P2 {
	  typealias Index = Int

which, of course, implies that one can use various tricks with constrained protocol extensions and such. There isn’t any proposed change here, but it illustrates that Swift programmers aren’t without recourse if type inference for associated types go away.

One concern with applying the above tricks is that existing code can change meaning when inference goes away. For example, let’s think about the “Iterator” type of a Sequence. It already uses default associated type witnesses (not associated type witness inference!) to give a default of IndexingIterator<Self>, e.g.,

	protocol Sequence {
	  associatedtype Iterator: IteratorType
	  func makeIterator() -> Iterator

	protocol Collection : Sequence {
	  associatedtype Iterator = IndexingIterator<Self>
	  func makeIterator() -> Iterator  // redeclaration helps inference

When a type that conforms to Collection doesn’t provide makeIterator, it gets a default one via:

	extension Collection where Iterator == IndexingIterator<Self> {
	  public func makeIterator() -> IndexingIterator<Self> { … }

That will still work (yay). However, simply removing associated type inference means that a collection type that *does* provide makeIterator()—but not, directly, Iterator—would change behavior:

	struct IntCollection : Collection {
	  typealias Element = Int
	  func makeIterator() -> IntCollectionIterator { … }

With associated type inference, we infer Iterator = IntCollectionIterator and select IntCollection.makeIterator() to satisfy the makeIterator() requirement.

Without associated type inference, we use the default Iterator = IndexingIterator<Self> and select the makeIterator() from the protocol extension (because IntCollection.makeIterator() now returns the wrong type), which turns an error of omission into an unpleasant surprise. We might need something like near-miss checking for defaulted protocol requirements (which we discussed in the thread at http://thread.gmane.org/gmane.comp.lang.swift.devel/1799) to help find those surprises. They already exist today, of course, but removing associated type inference would make them worse.

Finally, one of the chief concerns is that we won’t be able to provide a nice experience when conforming to the standard library’s collection protocols. I would *love* to see some more thought to into how we can use the above tools to handle it, although I suspect the only way to do that is to implement some part of this proposal experimentally and see what it takes to get the standard library and it’s tests working again. How far can the tools above go toward reducing the need to specify various associated type witnesses in conforming types? What are the surprises?

	- Doug

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160628/3c147aa0/attachment.html>

More information about the swift-evolution mailing list