<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=""><div class="">Hi Xiaodi and Charles,</div><div class=""><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">As I said, this discussion has already happened several times. I'm literally just repeating what people said eight months ago, six months ago, and four months ago. There's not a good answer to this and perhaps several other issues, which is why I don't see a way forward for the proposal. After all, I was the one proposing the same idea last winter, so I've had a few months to think about it.</div></div></div></div></blockquote></div><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div></div></div></div></div><div class="">I've been following the discussion from the side both now and before. Without being able to cover everything that's been said, I hope this message brings at least a bit of new air into the discussion.</div><div class=""><br class=""></div><div class="">— — —</div><div class=""><br class=""></div><div class="">Here's one more approach that, AFAICT, would enable both retroactive modelling and fairly good error diagnostics: <b class="">bring the full protocol conformance together with a dedicated definition block</b>&nbsp;which can both define implementations and refer to implementations defined elsewhere.</div><div class=""><br class=""></div><div class=""><b class="">Details:</b></div><div class=""><br class=""></div><div class="">1. Allow marking the conformance to a given protocol with a block of code. This could be nested inside a struct/enum/class body or its extension:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; <b class="">struct</b> Vector {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;<b class="">conformance</b> Hashable {&nbsp;</font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">/* TBD, read on… */</span><font face="Menlo" class="">&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; <b class="">extension</b> Vector {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;<b class="">conformance</b> CustomStringConvertible {&nbsp;</font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">/* … */</span><font face="Menlo" class="">&nbsp;}</font></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div></div><div class=""><br class=""></div><div class="">or at the top level, as a clearly marked <i class="">single-conformance extension</i>:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; <b class="">conformance</b> Vector : CustomDebugStringConvertible {&nbsp;</font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">/* … */</span><font face="Menlo" class="">&nbsp;}</font></div><div class=""><br class=""></div><div class="">2. Inside the body of that block, all protocol (non-extension) methods&nbsp;<b class="">must</b> be marked with `override`. That includes both the required interface and the customisable interface with library-provided default implementations:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; <b class="">struct</b> Vector {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <b class="">conformance</b> Hashable {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<b class="">override static func</b> ==(lhs: <b class="">Self</b>, rhs: <b class="">Self</b>) -&gt; Bool { <font color="#919191" class="">/* … */</font> }</font></div><div class=""><font face="Menlo" color="#919191" class="">&nbsp; &nbsp; &nbsp; &nbsp; // Ok.</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<font color="#ff2600" class=""><b class="">var</b> hashValue: Int</font> {&nbsp;</font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">/* … */</span><font face="Menlo" class="">&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; <font color="#919191" class="">// </font><b class=""><font color="#ff2600" class="">error:</font></b><font color="#919191" class=""> property 'hashValue' is required by Hashable.</font></font></div><div class=""><font face="Menlo" color="#919191" class="">&nbsp; &nbsp; &nbsp; &nbsp; // (Fixit: mark with 'override')</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<font color="#ff2600" class=""><b class="">override static func</b> &lt; (lhs: <b class="">Self</b>, rhs: <b class="">Self</b>) -&gt; Bool</font> {&nbsp;</font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">/* … */</span><font face="Menlo" class="">&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; <font color="#919191" class="">// </font><b class=""><font color="#ff2600" class="">error:</font></b><font color="#919191" class=""> protocol Hashable does not require 'static func &lt;'.</font></font></div><div class=""><font face="Menlo" color="#919191" class="">&nbsp; &nbsp; &nbsp; &nbsp; // (Fixit #1: remove override. Etc.)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div></div><div class=""><br class=""></div><div class="">3. When conformance is made explicit as described above, no other part of code is allowed to interfere with that type's conformance to the protocol under question:</div><div class=""><br class=""></div><div class=""><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;</span><b style="font-family: Menlo;" class="">conformance</b><span style="font-family: Menlo;" class="">&nbsp;</span><span style="font-family: Menlo;" class="">Vector : Collection {</span></div></div></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <b class="">override var </b>startIndex: Int { <b class="">return</b> 0 }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;</font><b style="font-family: Menlo;" class="">override&nbsp;</b><b style="font-family: Menlo;" class="">var</b><span style="font-family: Menlo;" class=""> endIndex: Int { </span><b style="font-family: Menlo;" class="">return</b><span style="font-family: Menlo;" class=""> _count }</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;</font><b style="font-family: Menlo;" class="">override&nbsp;</b><b style="font-family: Menlo;" class="">subscript</b><span style="font-family: Menlo;" class="">(index: Int) -&gt; Double { </span><b style="font-family: Menlo;" class="">return</b><span style="font-family: Menlo;" class=""> _elements[index] }</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;</font><b style="font-family: Menlo;" class="">override&nbsp;</b><b style="font-family: Menlo;" class="">func</b><span style="font-family: Menlo;" class="">&nbsp;index(after i: Int) -&gt; Int { </span><b style="font-family: Menlo;" class="">return</b><span style="font-family: Menlo;" class=""> i + 1 }</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; <b class="">extension</b>&nbsp;Vector {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <font color="#ff2600" class=""><b class="">var</b> count: Int</font> { <b class="">return</b> _count }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <font color="#919191" class="">// </font><b class=""><font color="#ff2600" class="">error:</font></b><font color="#919191" class="">&nbsp;property 'count' was introduced by explicit conformance&nbsp;</font></font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">to Collection.</span></div><div class=""><font face="Menlo" class=""><font color="#919191" class="">&nbsp; &nbsp; &nbsp; // (Fixit: Add explicit override to the conformance block.)</font></font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div><div class=""><br class=""></div><div class="">4a. When using a `conformance` block for retroactive modelling, or to explicitly include methods, properties etc. defined elsewhere, it is enough to list those in the body of the `conformance` block:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;<b class="">protocol</b>&nbsp;CountHaving {</font></div></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <b class="">associatedtype</b>&nbsp;Count : Integer</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <b class="">var</b>&nbsp;count: Count</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; <b class="">conformance</b>&nbsp;Array : HasCount {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; <b class="">override var</b> count: Int <font color="#919191" class="">// Ok, explicit retroactive modelling.</font></font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div><div class=""><br class=""></div><div class="">4b. Any override declarations without a body within an explicit `conformance` block are requirements for the definitions to exist elsewhere. That includes overridden properties without getters and setters. For example, here's an alternative way of fixing the error in #4:</div><div class=""><br class=""></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;</span><b style="font-family: Menlo;" class="">conformance</b><span style="font-family: Menlo;" class="">&nbsp;</span><span style="font-family: Menlo;" class="">Vector : Collection {</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;<b class="">override var&nbsp;</b>startIndex: Int {&nbsp;<b class="">return</b>&nbsp;0 }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;</font><b style="font-family: Menlo;" class="">override&nbsp;</b><b style="font-family: Menlo;" class="">var</b><span style="font-family: Menlo;" class="">&nbsp;endIndex: Int {&nbsp;</span><b style="font-family: Menlo;" class="">return</b><span style="font-family: Menlo;" class="">&nbsp;_count }</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;</font><b style="font-family: Menlo;" class="">override&nbsp;</b><b style="font-family: Menlo;" class="">subscript</b><span style="font-family: Menlo;" class="">(index: Int) -&gt; Double {&nbsp;</span><b style="font-family: Menlo;" class="">return</b><span style="font-family: Menlo;" class="">&nbsp;_elements[index] }</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;</font><b style="font-family: Menlo;" class="">override&nbsp;</b><b style="font-family: Menlo;" class="">func</b><span style="font-family: Menlo;" class="">&nbsp;index(after i: Int) -&gt; Int {&nbsp;</span><b style="font-family: Menlo;" class="">return</b><span style="font-family: Menlo;" class="">&nbsp;i + 1 }</span></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; <b class="">override var</b> count: Int <font color="#919191" class="">// No body; defined elsewhere.</font></span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;<b class="">extension</b>&nbsp;Vector {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp;<b class="">var</b>&nbsp;count: Int&nbsp;{ <b class="">return</b> _count } <font color="#919191" class="">// Ok.</font></font></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; }</span></div><div class=""><br class=""></div><div class="">5. Just like any other extensions, `conformance` blocks could introduce other non-`override` methods etc. to its needs, but they probably should keep it at minimum.</div><div class=""><br class=""></div><div class="">— — —</div><div class=""><br class=""></div><div class=""><b class="">Downsides.&nbsp;</b>Now, there are obvious reasons not to introduce this complexity to the language:</div><div class=""><br class=""></div><div class="">− It adds quite a bit of boilerplate to the conformance definition. (OTOH, programmers in a hurry would still be able to use the existing implicit conformance syntax, thereby avoiding the boilerplate on the one hand, and the better diagnostics on the other.)</div><div class=""><br class=""></div><div class="">− It would make it harder to add new required methods with default implementations without breaking code elsewhere. Because explicitly conforming types which already happened to have a matching function, property, or subscript would need to include it in the explicit conformance block. (OTOH, maybe that's what they indeed asked for by making the conformance explicit!)</div><div class=""><br class=""></div><div class="">− It would add yet another keyword to the language, context-specific but regardless. And the amount of `override` noise isn't looking very pretty.</div><div class=""><br class=""></div><div class="">− It possibly complicates some other convenient use of protocols that I can't think of right now. Discuss.</div><div class=""><br class=""></div><div class=""><b class="">On the plus sides,</b></div><div class=""><br class=""></div><div class="">+ There are precedents of explicit conformances in other languages:&nbsp;<a href="https://en.wikibooks.org/wiki/Haskell/Classes_and_types#Classes_and_instances" class="">Haskell's type classes</a>&nbsp;and&nbsp;<a href="http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/extend" class="">Clojure's protocols</a>&nbsp;come to mind as most similar.</div><div class=""><br class=""></div><div class="">+ It better documents how exactly the type conforms to the protocol, without leaving any missing "magic" elsewhere in the codebase. And it would become a compiler-enforced way to the already existing practice of keeping a conformance interface together within an extension block.</div><div class=""><br class=""></div><div class=""><b class="">Alternatives to consider:</b></div><div class=""><br class=""></div><div class="">A. Instead of nesting `conformance ProtocolName`, we could say `conformance Self : ProtocolName`.</div><div class=""><br class=""></div><div class="">B. Instead of introducing a new keyword `conformance` for top-level single-conformance extensions, we could state that `private/internal/public` in front of the `extension` keyword is used to define an explicit conformance of one protocol:</div><div class=""><br class=""></div><div class=""><b style="font-family: Menlo;" class="">&nbsp; &nbsp; internal extension</b><span style="font-family: Menlo;" class="">&nbsp;</span><span style="font-family: Menlo;" class="">Vector : Collection { <font color="#919191" class="">/* just Collection things */</font> }</span></div><div class=""><br class=""></div><div class="">— Pyry</div><div class=""><br class=""></div></body></html>