<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 24, 2016, at 11:38 AM, Douglas Gregor &lt;<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Aug 22, 2016, at 9:59 PM, Jonathan Hull 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=""><div class="">Hi everyone,<br class=""><br class="">We talked about this before when we were discussing mixins, and there seemed to be generally positive feelings towards it as a feature for the future. &nbsp;I am fairly certain this affects the ABI though, so I thought I would bring it up now.<br class=""><br class="">If two protocols have methods/properties with the same name, but different signatures, we need a way to distinguish between them when attempting to conform to both.<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>protocol A {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var x:Int {get set}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>protocol B {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var x:Double {get set}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">I believe that this can happen, and it is unfortunate that Swift has no mechanism for dealing with it today. However, I agree with Xiaodi that your proposal would be much stronger with real-world examples rather than theoretical ones.</div></div></div></blockquote><div><br class=""></div><div>Agreed. Unfortunately, everything is NDA’d at the moment. &nbsp;</div><div><br class=""></div><div>Also, the problem (not the solution) is so obvious to me that I guess I am having trouble explaining it. &nbsp;I never expected to have to argue that namespace collisions can cause problems… I thought everyone had had that experience (especially coming from ObjC).</div><div><br class=""></div><div>I am not tied to this proposal, so much as I wanted to start a discussion exploring the possible solution space. &nbsp;The explicit interface idea is a solid option. &nbsp;I like that you wouldn’t necessarily have to expose a protocol’s members without qualification. I should also be able to effectively rename a member by calling the unexposed protocol implementation from a method with my desired name.</div><div><br class=""></div><div>tl;dr: &nbsp;I would like people to provide options/syntax for solving this problem (even if they are a bit wild), so that we can cherry pick the best stuff and put together an elegant solution…</div><div><br class=""></div><div>Thanks,</div><div>Jon</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="">One possibility is to allow a struct/class/enum to conform to the protocol while renaming one (or both) of the clashing methods:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>struct C: A,B {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var x:Int<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var y:Double implements B.x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class="">The conforming method/property would still have to have the same signature, but could have a different name (and parameter labels). &nbsp;It would also allow protocol methods which have identical signatures and semantics, but different names to be implemented using the same method (i.e ‘implements D.z &amp; E.w’).<br class=""><br class="">When something is cast to the protocol (say ‘as B’), then calling the property (e.g. ‘x’) would end up calling the implementation of the renamed property ( ‘y’ in this example) on the conforming type.<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">Sure. Calling through the protocol type will get whatever method/property satisfied the protocol requirement. Yes, there are limits here due to protocols with associated types and Self requirements, but I fully expect those to go away at some point with generalized existentials.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class="">I think we would also want a way to retroactively conform using existing properties/methods in an extension declaring conformance. &nbsp;Not sure what the best syntax for that would be. &nbsp;Off the top of my head (though I would love to have something with less cruft):<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>extension D:B {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>@conform(to: B.x, with: D.y)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class="">or maybe just:<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>extension D:B {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>D.y implements B.x<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><br class="">All of this is merely to start the discussion, so feel free to propose better syntax or a more elegant solution...<br class=""></div></div></blockquote></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">C# has a much narrower solution that lets you qualify the method declaration (rather than doing a full rename), e.g.,</span><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>struct C : A {</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; var x: Int</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; var y: Double</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>extension C : B {</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; var B.x: Double {</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; &nbsp; get { return y }</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; &nbsp; set { y = newValue }</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; }</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><br class=""></div><div class="">They have some examples at:</div><div class=""><br class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><a href="https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx" class="">https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx</a></div><div class=""><br class=""></div><div class="">One would have to figure out what the name-lookup rules are, of course, but this might allow us to solve the problem without introducing a generalized renaming mechanism.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>- Doug</div></div></div></div></blockquote></div><br class=""></body></html>