[swift-evolution] [Completing Generics] Completing protocol extension diagnostics

T.J. Usiyan griotspeak at gmail.com
Tue Mar 8 11:24:53 CST 2016


```
struct InconsistentChannel {}

extension InconsistentChannel: Channel {
  func receive() -> NSData { ... } // OK
  func recieve() -> NSData { ... } // Warning: Declaration in conformance
extension doesn't satisfy any requirements from 'Channel'
  func doSomething() -> NSData? { ... } // Warning
}
```

Would/Could the warning be silenced if `doSomething()` is called by one of
the methods that do satisfy requirements? (I know that it is possible, is
it reasonable?)

TJ


On Tue, Mar 8, 2016 at 11:34 AM, Tim Schmelter via swift-evolution <
swift-evolution at swift.org> wrote:

> If we adopt the "one extension per conformance" model, would the compiler
> then warn us if we include, say, helper functions that exist only to aid in
> that conformance (and would therefore be appropriate to include in the
> extension)? Wouldn't that lead to polluting the main type with those helper
> methods?
>
> --T
>
>
> On Fri, Mar 4, 2016 at 3:38 AM, Haravikk via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> 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.
>>
>> 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.
>>
>> On 4 Mar 2016, at 00:08, Joe Groff via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>> 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:
>>
>> 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:
>>
>> protocol Channel {
>>   func receive() -> NSData
>> }
>> extension Channel {
>>   func receive() -> NSData { return NSData() }
>> }
>>
>> // Silently fails to replace the default implementation:
>> struct ClumsyChannel: Channel {
>>   // Wrong spelling
>>   func recieve() -> NSData { return NSData(bytes: "oops", length: 4) }
>>   // Wrong return type
>>   func receive() -> [UInt8] { return Array("whoopsie".utf8) }
>>   // Wrong throwiness
>>   func receive() throws -> NSData { throw "doh" }
>> }
>>
>> 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:
>>
>> class BaseChannel: Channel { } // gets default imp from extension
>>
>> class SubChannel: BaseChannel {
>>   // Doesn't 'override' protocol requirement; silently shadows it
>>   func receive() -> NSData { return NSData(bytes: "oof", length: 3) }
>> }
>>
>> 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:
>>
>> extension Channel {
>>   func receiveAsString() -> String {
>>     return String(data: receive(), encoding: NSUTF8Encoding)
>>   }
>> }
>>
>> struct StringyChannel {
>>   func receive() -> NSData { return NSData(bytes: "data", 4) }
>>   // Does not affect generic code calling receiveAsString
>>   func receiveAsString() -> String { return "string" }
>> }
>>
>> func foo<T: Channel>(chan: T) {
>>   print(chan.receiveAsString())
>> }
>>
>> foo(StringyChannel()) // Prints "data"
>>
>> (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:
>>
>> - 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.
>> - 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:
>>
>> struct InconsistentChannel {}
>>
>> extension InconsistentChannel: Channel {
>>   func receive() -> NSData { ... } // OK
>>   func recieve() -> NSData { ... } // Warning: Declaration in conformance
>> extension doesn't satisfy any requirements from 'Channel'
>>   func receive() -> NSData? { ... } // Warning
>> }
>>
>> There are likely others too. It'd be great if we could give users better
>> guidance about this feature.
>>
>> -Joe
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160308/266f59e0/attachment.html>


More information about the swift-evolution mailing list