<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="">I’m using String as an example of where this issue of conformance conflicts crops up in the standard library. Ideally, String (or any data type) should be able to conform to protocols whose requirements have conflicting names.</div><div class="">Currently, in order to work around this limitation, you have to delegate the conformance to a supporting type. This is more complicated to write and maintain, and pollutes your internal API. String gives us an example of this, but it’s not the worst example.</div><div class="">It basically implements what I’m talking about anyway, but manually via a supporting type instead of directly inside the data-type (String). As an ABI consideration, we should scope all protocol members to their protocols. This would resolve all naming conflicts.</div><div class=""><br class=""></div><div class="">I can’t understand how anybody would argue for the status quo - we’re currently in-between two ideas of what protocols should be - they are explicit but their conformances are resolved by name only and can overlap without warning.</div><br class=""><div><blockquote type="cite" class=""><div class="">On 21 Sep 2016, at 00:48, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="white-space:pre-wrap" class="">Sorry, I'm still not sure I understand what you're getting at about this. How would String conforming to Collection multiple times simplify or improve the implementation of String? Or are you arguing it would be better for users of String? If so, how?<br class=""></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Sep 20, 2016 at 17:26 Karl &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">I’m not saying vital support is missing, just that it is more awkward. String doesn’t conform to collection, String.UTF8View does; so if you change some implementation detail (in StringCore, because that’s where they live for String), you get the error popping up somewhere other than the place you just changed. That’s what I mean when I say “language support”. If you do what StringCore does, and you’re changing stuff which is ultimately going to be used to conform to, say, Collection, you have to build distance between the implementation and the (only) conformance it is used for, and it’s less optimal.<div class=""><br class=""></div><div class="">Let’s say I have an object MyComplexDataType, it implements “InternalStructureView” and “Collection”:</div><div class=""><br class=""></div><div class="">```</div><div class="">protocol InternalStructureView {</div><div class="">&nbsp; &nbsp; associatedtype Index</div><div class="">&nbsp; &nbsp; var count : Int { get } // whatever, just some stuff that will cause a name conflict</div><div class="">&nbsp; &nbsp; func doInternalMagic(at: Index)</div><div class="">}</div><div class=""><br class=""></div><div class="">struct MyComplexDataType {</div><div class="">&nbsp; &nbsp; var __collection_count : Int {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // This is quite a complex operation which we’d rather leave inside the type, otherwise we’d need to expose a bunch of implementation details internally</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp;var __internal_count : Int {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;// Again, best left here</div><div class="">&nbsp; &nbsp;}</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;struct CollectionView &nbsp;: Collection {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;init(parent: MyComplexDataType) { … }</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; var count { return parent.__collection_count }</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // ...etc</div><div class="">&nbsp; &nbsp;}</div><div class=""><br class=""></div><div class="">&nbsp; struct InternalStructure : InternalStructureView {</div><div class="">&nbsp; &nbsp; &nbsp; init(parent: MyComplexDataType) { … }</div><div class="">&nbsp; &nbsp; &nbsp; var count { return parent.__internal_count }</div><div class="">&nbsp; &nbsp; &nbsp; // ...etc</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; var collection : CollectionView { return CollectionView(self) }</div><div class="">&nbsp; var internalStructure : InternalStructure { return InternalStructure(self) }</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">This is basically what String does (except that it wants to conform to Collection multiple times with different indexes and results). It’s a lot of work to maintain, especially if you have evolving protocols that are conformed to in several places.</div><div class="">We should have a better solution. We should be able to define:</div><div class=""><br class=""></div><div class="">“protocol UTF8Collection : Collection {}</div><div class="">&nbsp;protocol UTF16Collection : Collection {}”</div><div class=""><br class=""></div><div class="">and have String conform to both of them at the same time. At the same time, since we’re now being explicit about which protocol requirement is satisfied where - we should also be able to delegate our conformance, telling the compiler to dispatch any unimplemented methods to another object. For example, lets say you want to wrap a Collection and observe mutations to it; you might override replaceSubrange(), but every other method (such as count, index(after:)… all the rest) is just a forwarding function.</div><div class=""><br class=""></div><div class="">Interestingly, we could do this safely (from a code legibility perspective) if we say that every scope which adds a conformance must completely satisfy its requirements, which we would more reasonably be able to require if we made this change (so your internal functions can still be wherever you like, but they won’t automatically satisfy a protocol requirement if they happen to have the same name). Then we could reasonably say that if you add an extension which adds a conformance to, say, Collection, you have to tell us where to find every one of its requirements. That’s where we could put the forwarding syntax for retroactive modelling. Stored properties can’t be defined in extensions, so if you want to back an implementation with one, you’ll need to make its conformance explicit in the main body (or we loosen that to at least extensions in the same file).</div><div class=""><br class=""></div><div class="">```</div><div class="">// generates thunks to members of this extension in the base type;&nbsp;</div><div class="">// so MyComplexDataType.count —&gt; MyComplexDataType.InternalStructure.count,</div><div class="">// to account for conformance being added in later version. Can also be used for renamed protocols, and be tagged on individual members.</div><div class=""><br class=""></div><div class="">@makeAvailable(as: _)</div><div class="">extension MyComplexDataType : InternalStructure {</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;typealias Index = InternalIndexType</div><div class="">&nbsp; &nbsp; var count : Int {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // We have access to all of the private members because we’re inside MyComplexDataType</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // No need to pollute internal API with conformance implementation details.</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; // Also, we get errors about non-conformance where we want them — where the implementation is.</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; func doInternalMagic(at: Index) {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;...</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class="">```</div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 20 Sep 2016, at 23:46, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class="">I'm not sure I understand. What compiler or language support is missing for StringCore?<br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><div class="">On 20 Sep 2016, at 23:28, Karl &lt;<a href="mailto:raziel.im+swift-evo@gmail.com" target="_blank" class="">raziel.im+swift-evo@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div style="word-wrap:break-word" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class=""><div class=""><div dir="ltr" class="">I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.<div class=""><br class=""></div><div class="">It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.</div><div class=""><br class=""></div><div class="">When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.</div><div class=""><br class=""></div><div class="">In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.</div><div class=""><br class=""></div><div class="">However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.<br class=""></div><div class=""><br class=""></div><div class="">Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.</div><div class=""><br class=""></div><div class="">On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.</div><div class=""><br class=""></div><div class="">A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.</div><div class=""><br class=""></div><div class="">The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.</div><div class=""><br class=""></div><div class="">I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.</div><div class=""><br class=""></div><div class="">Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.</div><div class=""><br class=""></div><div class="">A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.</div><div class=""><br class=""></div><div class="">Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.<br class=""></div><div class=""><br class=""></div><div class="">Nevin</div><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.<div class=""><div class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br class="">
&nbsp;&gt; extension P {<br class="">
&nbsp;&gt; implement func foo() -&gt; [String : String] { return [:] }<br class="">
&nbsp;&gt; }<br class="">
<br class="">
Yes, it seems like we need `implement` (or `override` as another<br class="">
suggestion) in protocol extension also just for the same reasons - be clear<br class="">
about our intention regarding implementing the requirement, to show that<br class="">
this func *depends* on the previous definition of P protocol and to avoid<br class="">
possible mistakes related to protocol conformance.<br class="">
<br class="">
On 20.09.2016 17:38, Charles Srstka wrote:<br class="">
&gt;&gt; On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution<br class="">
&gt;&gt; &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;&gt; wrote:<br class="">
&gt;&gt;<br class="">
&gt;&gt; On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:<br class="">
&gt;&gt;&gt; I definitely think Vladimir's suggestion is a great starting point, IMO.<br class="">
&gt;&gt;&gt;<br class="">
&gt;&gt;&gt; However, I think it could be improved in one key respect where previous<br class="">
&gt;&gt;&gt; proposals using `override` are superior. Namely, the proposed `implement`<br class="">
&gt;&gt;&gt; keyword adds no additional safety when a type implements a protocol<br class="">
&gt;&gt;&gt; requirement that doesn't have a default implementation. This is because, if<br class="">
&gt;&gt;<br class="">
&gt;&gt; Yes, *at the moment of writing* the type's code there could be no default<br class="">
&gt;&gt; implementation for protocol requirement. But, *at the moment of<br class="">
&gt;&gt; compilation* such default implementation could appear.<br class="">
&gt;&gt;<br class="">
&gt;&gt; Let's discuss such scenario in case we'll take your suggestion:<br class="">
&gt;&gt;<br class="">
&gt;&gt; You got SomeClass.swift file, 3rd party file you don't want to change or<br class="">
&gt;&gt; changes are not allowed. Content:<br class="">
&gt;&gt;<br class="">
&gt;&gt; public protocol SomeProtocol {<br class="">
&gt;&gt; func foo()<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; public class SomeClass : SomeProtocol {<br class="">
&gt;&gt; func foo() {...} // no default implementation *at the moment of writing*,<br class="">
&gt;&gt; no need in `overload`<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; Now, you adds SomeClass.swift file to your project and in some *other*<br class="">
&gt;&gt; file you write:<br class="">
&gt;&gt;<br class="">
&gt;&gt; extension SomeProtocol {<br class="">
&gt;&gt; func foo() {...}<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; As you see, you don't control the SomeClass.swift but you suggest in this<br class="">
&gt;&gt; case SomeClass.foo() should be defined with `override`.<br class="">
&gt;&gt;<br class="">
&gt;&gt; With 'implement' SomeClass.foo() will be marked initially and will save<br class="">
&gt;&gt; us if protocol's requirement PLUS default implementation changed.<br class="">
&gt;<br class="">
&gt; Requiring the ‘implement’ keyword can help us even if no default<br class="">
&gt; implementation is involved. Consider:<br class="">
&gt;<br class="">
&gt; protocol P {<br class="">
&gt; func foo() -&gt; [String : Any]<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; struct S : P {<br class="">
&gt; func foo() -&gt; [String : String] { return [:] }<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; We will get an error here that S does not conform to P. However, this is<br class="">
&gt; not the correct error, since S in fact *tries* to conform to P, but it has<br class="">
&gt; a mistake in a method signature. This misleads us as to the true nature of<br class="">
&gt; the problem, and if S has enough members in it that we fail to spot the<br class="">
&gt; existing foo(), we might solve the problem by reimplementing foo(), and<br class="">
&gt; leaving the original foo() as dangling dead code. Having an ‘implement’<br class="">
&gt; keyword on the existing foo() function would change the compiler error to<br class="">
&gt; let us know that we have an existing foo() that is incorrectly declared.<br class="">
&gt;<br class="">
&gt; In addition, ‘implement’ can help us when the declaration in question *is*<br class="">
&gt; the default implementation:<br class="">
&gt;<br class="">
&gt; protocol P {<br class="">
&gt; func foo() -&gt; [String : Any]<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; extension P {<br class="">
&gt; implement func foo() -&gt; [String : String] { return [:] }<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; Here we will get an error with the proposed ‘implement’ keyword, because<br class="">
&gt; foo() does not have a signature matching anything in the protocol, whereas<br class="">
&gt; without ‘implement’ we would happily and silently generate a useless<br class="">
&gt; dangling function that would never be used, and then pass the buck to the<br class="">
&gt; concrete type that implements P:<br class="">
&gt;<br class="">
&gt; protocol P {<br class="">
&gt; func foo() -&gt; [String : Any]<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; extension P {<br class="">
&gt; func foo() -&gt; [String : String] { return [:] } // The error is here:<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; struct S : P {} // But it gets reported here.<br class="">
&gt;<br class="">
&gt; Charles<br class="">
&gt;<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div>
</div></div><br class="">_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote><br class=""></div><div class=""><br class=""></div><div class="">I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.</div><div class=""><br class=""></div><div class="">I think the best way is to prefix the member name with the protocol, e.g:</div><div class=""><br class=""></div><div class="">protocol MyProto {</div><div class="">&nbsp; &nbsp; var aVariable : Int</div><div class="">&nbsp; &nbsp; func aFunction()</div><div class="">}</div><div class="">class MyClass : MyProto {</div><div class="">&nbsp; &nbsp; var MyProto.aVariable : Int</div><div class="">&nbsp; &nbsp; func MyProto.aFunction() { … }</div><div class="">}</div><div class=""><br class=""></div><div class="">This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.</div><div class="">As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?</div><div class=""><br class=""></div><div class="">The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.</div><div class=""><br class=""></div><div class="">I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.</div><div class=""><br class=""></div><div class="">We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.</div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.</div><div class="">String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.</div><div class=""><br class=""></div><div class="">The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><div class="">I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.</div><div class=""><br class=""></div><div class="">Karl</div><br class=""><div class=""><br class=""></div><div class=""><div class="">CC-ing Dave A, to understand better if this fits with the vision of protocols</div></div><div class=""><br class=""></div></div></div></blockquote></div></div>_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></div></div></blockquote></div>
</div></blockquote></div><br class=""></body></html>