<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br><br>Sent from my iPad</div><div><br>On Jun 25, 2016, at 12:41 PM, Austin Zheng &lt;<a href="mailto:austinzheng@gmail.com">austinzheng@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 25, 2016, at 6:23 AM, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi Austin,</div><div class=""><br class=""></div>I’m sorry to say, but this proposal makes me really sad. &nbsp;I consider associated type inference one of the more elegant aspects of Swift. &nbsp;It would be very unfortunate to lose it. &nbsp;</div></div></blockquote><div><br class=""></div><div>There are lots of "elegant" things that Swift could do, but has chosen not to do for pragmatic reasons (e.g. generalized implicit conversions, type inference that crosses statement boundaries). Given how terrible the development experience can be right now in the worst case, I would happily trade off some measure of convenience for better tooling.</div></div></div></blockquote><div><br></div><div>I understand the technical issues underlying the proposal. &nbsp;I wasn't sure how I would respond to this until Dmitri posted an alternative. &nbsp;IMO if we can solve the technical issues without giving up inference that is a huge win. &nbsp;It looks viable to me (as a non-expert - I hope a compiler engineer can confirm this).</div><div><br></div><div>If this is indeed a viable alternative then there is no tradeoff necessary and the discussion becomes one of style / preference. &nbsp;In that discussion I fall strongly on the side of protocol requirement guided inference.</div><div><br></div><blockquote type="cite"><div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">I am really pleased to see that Dmitri has offered an alternative that looks very reasonable. &nbsp;I’m hoping the Doug or Chris (or someone else from the core team) can chime in on the feasibility of this alternative. &nbsp;If it is considered viable and Dmitri isn’t able to write the proposal I would be happy to do so.<div class=""><br class=""></div><div class="">If the alternative isn’t viable and we must proceed with a proposal to remove inference I think there is one crucial thing to consider that isn’t discussed in this proposal: retroactive modeling. &nbsp;As far as I can tell, this proposal will *prohibit* some types from conforming to some protocols. &nbsp;Specifically, if a type defines a typealias with a name that matches the name of an associatedtype in a protocol it would not be possible to retroactively model that protocol. &nbsp;Because of the name conflict an associatedtype declaration would not be allowed and the existing typealias would not meet the requirement. &nbsp;Consider this example:</div></div></div></div></blockquote><div><br class=""></div><div>I actually think that the delineation between `associatedtype` and `typealias` should make this legal, and will change the proposal as such. It should be legal to bind an associated type to a type alias, and it should be possible to define a type alias that shadows (but does not conflict with) an associated type definition. This would fix the issue with retroactive modeling.</div></div></div></blockquote><div><br></div>IIUC you're saying a type is allowed to have an <span style="background-color: rgba(255, 255, 255, 0);">`associatedtype` and `typealias` (or nested type) both bound to the same name as long as they resolve to the same type. &nbsp;Is that correct? &nbsp;That would at least preserve current expressiveness.</span><div><br><blockquote type="cite"><div><div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">// Module A</div><div class="">public struct S {</div><div class="">&nbsp; &nbsp; public typealias Foo = Int</div><div class="">}</div><div class=""><br class=""></div><div class="">// Module B</div><div class="">public protocol P {</div><div class="">&nbsp; &nbsp; associatedtype Foo</div><div class="">}</div><div class=""><br class=""></div><div class="">// Module C</div><div class="">import A</div><div class="">import B</div><div class=""><br class=""></div><div class="">// compiler error: `S` does not meet the `Foo` associatedtype requirement</div><div class="">extension S : P {</div><div class="">&nbsp; &nbsp; // compiler error: cannot define associatedtype `Foo` for `S` which already declares typealias `Foo`</div><div class="">&nbsp; &nbsp; associatedtype Foo = String</div><div class="">}</div><div class=""><br class=""></div><div class="">I cannot support any proposal that breaks retroactive modeling in this way.</div></div></div></div></blockquote><div><br class=""></div><div>Addendum aside, retroactive modeling is already suboptimal or broken in multiple ways today - try conforming a protocol with associated type 'Element' to a different protocol whose 'Element' means something completely different.</div></div></div></blockquote><div><br></div><div>Did you mean conforming a type to two protocols with an 'Element' associatedtype?</div><div><br></div><div>I consider that issue to be in the realm of multiple conformances rather than retroactive modeling. &nbsp;I can still&nbsp;</div><br><blockquote type="cite"><div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">Another item that is not mentioned in this proposal is that typealias is not the only way to meet an associatedtype requirement in the language today. &nbsp;For example, this code is legal:</div><div class=""><br class=""></div><div class="">protocol&nbsp;Foo {<br class="">&nbsp; &nbsp;&nbsp;associatedtype&nbsp;Bar<br class="">}<br class="">struct&nbsp;S :&nbsp;Foo&nbsp;{<br class="">&nbsp; &nbsp;&nbsp;struct&nbsp;Bar {}<br class="">}</div></div></div></div></blockquote><div><br class=""></div><div>I don't see how this is relevant.</div><div><br class=""></div><div>struct S : Foo {</div><div>&nbsp; associatedtype S = Bar</div><div>&nbsp; struct Bar { }</div><div>}</div></div></div></blockquote><div><br></div>Do you mean this?</div><div><br></div><div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">struct S : Foo {</span></font></div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">&nbsp; associatedtype Bar = Bar</span></font></div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">&nbsp; struct Bar { }</span></font></div><div><font color="#000000"><span style="background-color: rgba(255, 255, 255, 0);">}</span></font></div></div><div><br></div><div>That would preserve current expressiveness.</div><div><br><blockquote type="cite"><div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">If we *must* drop inference I prefer the alternative of just doing that: dropping inference, but otherwise leaving things alone. &nbsp;All associated type requirements would need to be explicitly satisfied using one of the mechanisms that is currently valid for satisfying a non-inferred associated type requirement. &nbsp;The ability to satisfy these requirements in a variety of ways is a *benefit* that provides valuable flexibility.</div></div></div></div></blockquote><div><br class=""></div><div>I disagree that it's a benefit. It certainly saves a couple of keystrokes, but you gain or lose no expressive power from this proposal, addendum included. I'm happy to expand the alternatives section to discuss the other ways to satisfy associated type requirements, though.</div></div></div></blockquote><div><br></div><div>Thank you for adding the clarifications. &nbsp;I feel a little better knowing we wouldn't lose expressive power, but still prefer the directed inference suggested by Dmitri.</div><br><blockquote type="cite"><div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class=""><div class="">I agree that something should look for a good solution to the subclass typealias issue, but I don’t think this is it. &nbsp;Ideally we would find a solution that works well in the presence of retroactive modeling making code such as the following valid:</div><div class=""><br class=""></div><div class="">// module A</div><div class="">protocol&nbsp;P1 {<br class="">&nbsp; &nbsp;&nbsp;associatedtype&nbsp;Foo</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;@infers(Foo)<br class="">&nbsp; &nbsp;&nbsp;var&nbsp;foo: Foo {&nbsp;get&nbsp;}<br class="">}</div><div class="">// module B<br class="">protocol&nbsp;P2 {<br class="">&nbsp; &nbsp;&nbsp;associatedtype&nbsp;Foo</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; @infers(Foo)<br class="">&nbsp; &nbsp;&nbsp;func&nbsp;bar() -&gt; Foo<br class="">}<br class=""><br class="">// module C<br class="">class&nbsp;Base {<br class="">&nbsp; &nbsp;&nbsp;let&nbsp;foo:&nbsp;String&nbsp;=&nbsp;"foo"<br class="">}<br class="">class&nbsp;Derived :&nbsp;Base&nbsp;{<br class="">&nbsp; &nbsp;&nbsp;func&nbsp;bar() -&gt;&nbsp;Int&nbsp;{&nbsp;return&nbsp;42&nbsp;}<br class="">}</div></div><div class=""><br class=""></div><div class="">// module D</div><div class="">import A</div><div class="">import B</div><div class="">import C</div><div class="">import D</div><div class="">extension Base : P1 {}</div><div class="">extension Derived : P2 {}</div><div class=""><br class=""></div><div class="">We don’t always control the protocol or type definitions we want to make work together. &nbsp;The ability to make code that “should work together” actually do so with minimal fuss is one of the great things about Swift. &nbsp;Any time we interfere with retroactive modeling we increase the need for boilerplate adapter types, etc.</div><div class=""><br class=""></div><div class="">One detail appears to be implied by the proposal but isn’t explicitly stated. &nbsp;Specifically, it looks like the intent is that other than only being valid when used to meet a protocol requirement, associatedtype otherwise works like a typealias. &nbsp;It would be good to have this behavior clarified if the proposal moves forward.</div><div class=""><br class=""></div><div class="">-Matthew</div><div class=""><br class=""></div><div class=""><br class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 25, 2016, at 12:50 AM, Austin Zheng via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hello all,<div class=""><br class=""></div><div class="">Per Chris Lattner's list of open Swift 3 design topics (<a href="http://article.gmane.org/gmane.comp.lang.swift.evolution/21369" class="">http://article.gmane.org/gmane.comp.lang.swift.evolution/21369</a>), I've put together a proposal for removing type inference for associated types.</div><div class=""><br class=""></div><div class="">It can be found here:&nbsp;<a href="https://github.com/austinzheng/swift-evolution/blob/az-assoctypeinf/proposals/XXXX-remove-assoctype-inference.md" class="">https://github.com/austinzheng/swift-evolution/blob/az-assoctypeinf/proposals/XXXX-remove-assoctype-inference.md</a></div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Best,</div><div class="">Austin</div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></div></div></div></blockquote></div><br class=""></div></blockquote></div></body></html>