<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>The detailed design section of </div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature"> <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md">https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md</a></div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">Now talks about this. It's not a new problem, and I'm firstly confident that the near-miss checking approach will address the issues.<br><br>Sent from my iPhone</div><div><br>On Jun 29, 2016, at 8:16 AM, Brandon Knope <<a href="mailto:bknope@me.com">bknope@me.com</a>> wrote:<br><br></div><blockquote type="cite"><div><span>This is true! Swift is suppose to be a safe language that can prevent these kind of pitfalls. </span><br><span></span><br><span>But I feel there was a rationale for having the way it is...I just don't know it</span><br><span></span><br><span>Brandon </span><br><span></span><br><blockquote type="cite"><span>On Jun 29, 2016, at 10:21 AM, Sean Heber <<a href="mailto:sean@fifthace.com">sean@fifthace.com</a>> wrote:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Another issue here (perhaps) is, what if you misspelled the associated type when you attempted to typealias it manually? Would it not just make a new typealias with your misspelled name and then, potentially, you’d get an error or would something end up working but in unexpected ways? Would the typo be easy to identify if you had a lot of typealiases or associatedtypes or typos?</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> protocol P {</span><br></blockquote><blockquote type="cite"><span> associatedtype Index = Int</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> struct X : P {</span><br></blockquote><blockquote type="cite"><span> typealias index = String // whoops - no capital I - how long does this bug take to find? :P</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>There will always be bugs, of course. Maybe this isn’t a significant concern?</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>l8r</span><br></blockquote><blockquote type="cite"><span>Sean</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><blockquote type="cite"><span>On Jun 29, 2016, at 8:55 AM, Brandon Knope via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>What's the rationale for having associatedtype in protocols and typealias in the conforming types?</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>This has actually been a point of confusion for me as it seems inconsistent </span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>Brandon</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>Sent from my iPad</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>On Jun 29, 2016, at 1:33 AM, Douglas Gregor via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>On Jun 24, 2016, at 10:50 PM, Austin Zheng via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:</span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Hello all,</span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Per Chris Lattner's list of open Swift 3 design topics (<a href="http://article.gmane.org/gmane.comp.lang.swift.evolution/21369">http://article.gmane.org/gmane.comp.lang.swift.evolution/21369</a>), I've put together a proposal for removing type inference for associated types.</span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>It can be found here: <a href="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</a></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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.</span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Thanks for working on this. I have a couple of comments.</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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.</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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.,</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> protocol P {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> associatedtype Associated = Int</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> struct X : P {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> // Associated becomes Int if not otherwise specified</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>and with typealiases in protocol extensions becoming real and useful, one could also use protocol extensions:</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> protocol P2 {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> associatedtype Index</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> extension P2 {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> typealias Index = Int</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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.</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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.,</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> protocol Sequence {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> associatedtype Iterator: IteratorType</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> func makeIterator() -> Iterator</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> protocol Collection : Sequence {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> associatedtype Iterator = IndexingIterator<Self></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> func makeIterator() -> Iterator // redeclaration helps inference</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>When a type that conforms to Collection doesn’t provide makeIterator, it gets a default one via:</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> extension Collection where Iterator == IndexingIterator<Self> {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> public func makeIterator() -> IndexingIterator<Self> { … }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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:</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> struct IntCollection : Collection {</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> typealias Element = Int</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> func makeIterator() -> IntCollectionIterator { … }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> }</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>With associated type inference, we infer Iterator = IntCollectionIterator and select IntCollection.makeIterator() to satisfy the makeIterator() requirement.</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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 <a href="http://thread.gmane.org/gmane.comp.lang.swift.devel/1799">http://thread.gmane.org/gmane.comp.lang.swift.devel/1799</a>) to help find those surprises. They already exist today, of course, but removing associated type inference would make them worse.</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>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?</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span> - Doug</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>_______________________________________________</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>swift-evolution mailing list</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>_______________________________________________</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>swift-evolution mailing list</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></blockquote></blockquote><blockquote type="cite"><span></span><br></blockquote></div></blockquote></body></html>