<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 like the idea of encouraging "one extension per conformance", though I’d maybe adjust it to simply “add conformance through extension”, as sometimes it makes sense for a single extension to add conformance to multiple protocols at a time, for example an extension to add conformance to CustomDebugStringConvertible and CustomStringConvertible as a single item. I’m not sure if you intended to prevent that, but I think it should still be possible to allow multiple protocols with the same basic concept that conformance must be exact.</div><div class=""><br class=""></div><div class="">Regarding keyword usage for implementations, I’d say that we should have the override keyword at least on methods that shadow default implementations provided for protocol methods, as this should make things clearer. It could also help to tidy up documentation as currently default implementations that have been shadowed still show up in many places, even though they’re no longer strictly relevant.</div><br class=""><div><blockquote type="cite" class=""><div class="">On 4 Mar 2016, at 00:08, Joe Groff 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="">Under the umbrella of completing generics, I think we should make room for improving our diagnostics around protocol extensions. They're a well-received feature, but they introduce a lot of surprising behavior, and introduce opportunity for subtle bugs. We didn't have time to put much diagnostic work in last year, but now that users have had time to work with the feature, we have evidence of some of the more surprising and problematic behavior. Among the most common things we've seen reported:<div class=""><br class=""></div><div class="">A) When a protocol requirement has an extension implementation requirement available, we'll silently ignore when a conforming type attempts to conform to the protocol but misses, by type or spelling:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">protocol Channel {</div><div class="">&nbsp; func receive() -&gt; NSData</div><div class="">}</div><div class="">extension Channel {</div><div class="">&nbsp; func receive() -&gt; NSData { return NSData() }</div><div class="">}</div><div class=""><br class=""></div><div class="">// Silently fails to replace the default implementation:</div><div class="">struct ClumsyChannel: Channel {</div><div class="">&nbsp; // Wrong spelling</div><div class="">&nbsp; func recieve() -&gt; NSData { return NSData(bytes: "oops", length: 4) }</div><div class="">&nbsp; // Wrong return type</div><div class="">&nbsp; func receive() -&gt; [UInt8] { return Array("whoopsie".utf8) }</div><div class="">&nbsp; // Wrong throwiness</div><div class="">&nbsp; func receive() throws -&gt; NSData { throw "doh" }</div><div class="">}</div><div class=""><br class=""></div></blockquote>B) Protocol requirements aren't real class members, and can't be overridden by subclasses unless the base class satisfies the requirement with one of its own methods rather than with a protocol extension method, but we silently allow subclasses to shadow:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">class BaseChannel: Channel { } // gets default imp from extension</div><div class=""><br class=""></div><div class="">class SubChannel: BaseChannel {</div><div class="">&nbsp; // Doesn't 'override' protocol requirement; silently shadows it</div><div class="">&nbsp; func receive() -&gt; NSData { return NSData(bytes: "oof", length: 3) }</div><div class="">}</div><div class=""><br class=""></div></blockquote>C) Similarly, protocol extension methods aren't protocol requirements, so extension methods that don't match a requirement can't be specialized in a way available to generic code, but we silently allow concrete type implementations to shadow:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">extension Channel {</div><div class="">&nbsp; func receiveAsString() -&gt; String {</div><div class="">&nbsp; &nbsp; return String(data: receive(), encoding: NSUTF8Encoding)</div><div class="">&nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class="">struct StringyChannel {</div><div class="">&nbsp; func receive() -&gt; NSData { return NSData(bytes: "data", 4) }</div><div class="">&nbsp; // Does not affect generic code calling receiveAsString</div><div class="">&nbsp; func receiveAsString() -&gt; String { return "string" }</div><div class="">}</div><div class=""><br class=""></div><div class="">func foo&lt;T: Channel&gt;(chan: T) {</div><div class="">&nbsp; print(chan.receiveAsString())</div><div class="">}</div><div class=""><br class=""></div><div class="">foo(StringyChannel()) // Prints "data"</div><div class=""><br class=""></div></blockquote>(B) and (C) could be mitigated by shadowing warnings, and we've also floated ideas for making them behave as intended, by implicitly forwarding protocol requirements into class methods to address (B) and/or introducing dynamic dispatch for protocol extensions to address (C). (A) is a bit trickier, since with overloading it's tricky to divine whether a declaration was really intended to match another one with a different type in isolation. We've discussed a couple approaches to this problem:<div class=""><br class=""></div><div class="">- Adopting an explicit 'implements' modifier, in the spirit of 'override', to mark a declaration as being intended to fulfill a requirement. This adds boilerplate we'd like to avoid, and also interferes with retroactive modeling.</div><div class="">- Encourage "one extension per conformance" style, where each protocol conformance's requirements are defined in a dedicated extension. We can then warn about any declarations in an extension that don't satisfy a requirement:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">struct InconsistentChannel {}</div><div class=""><br class=""></div><div class="">extension InconsistentChannel: Channel {</div><div class="">&nbsp; func receive() -&gt; NSData { ... } // OK</div><div class="">&nbsp; func recieve() -&gt; NSData { ... } // Warning: Declaration in conformance extension doesn't satisfy any requirements from 'Channel'</div><div class="">&nbsp; func receive() -&gt; NSData? { ... } // Warning</div><div class="">}</div><div class=""><br class=""></div></blockquote>There are likely others too. It'd be great if we could give users better guidance about this feature.<div class=""><br class=""></div><div class="">-Joe</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="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>