[swift-evolution] [Proposal] clarification around protocol implementation and protocol extensions

Xiaodi Wu xiaodi.wu at gmail.com
Sat Feb 18 01:40:54 CST 2017


On Sat, Feb 18, 2017 at 1:07 AM, David Waite <david at alkaline-solutions.com>
wrote:

>
> > On Feb 17, 2017, at 10:53 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> >
> > This draft proposes something that's been discussed on this list several
> times over the past few years, but now with a different spelling. However,
> previous objections never centered around the spelling.
> >
> > As discussed in previous threads on this topic, any such required
> keyword breaks retroactive conformance. That is, if I want to conform
> someone else's type to my protocol, I must edit that person's code if your
> idea is accepted.
>
> I believe this proposal is different in that it only requires
> specification for clarity not for behavioral changes, and only requires the
> keyword to be specified for protocols known at the site of method/property
> declaration.
>

If indeed you frame your proposal in this way, a best effort to add clarity
of intention, my feedback is that there are ways to gain the same (or at
least, very similar) benefits without being source-breaking, and indeed
without introducing new keywords at all.

For example:
- Doc comments are parsed. We already have `- Parameter` in doc comments,
which improved tooling could double-check to ensure that the stuff we put
there matches the stuff in the function signature (hmm, that'd be a nice
additive proposal, right?).
- The same tool could be augmented to recognize a spelling such as `-
RequiredBy:`, and you could list the specific protocols that require the
method. Then, you would be warned at compiled time if your method is in
fact not required by a protocol. This design has the side benefit of
telling the reader of your code exactly what protocols require that method,
not just that it's required by some protocol.

>
> > In so doing, this idea rejects an important (essential, IMO) mental
> model of what protocol conformance entails. Specifically, I conform a type
> T to a protocol P when I discover, having already implemented T, that it
> fulfills the semantic and syntactic requirements of P. Unlike subclassing,
> I'm not setting out with the intention of making a type T that conforms to
> P; rather, I discover this fact to my great delight after implementation of
> T. The analogy to subclassing is therefore inaccurate. Notionally, one
> always inherits from a superclass first, then overrides.
> >
> > This is no mere theoretical notion. It is a Swift idiom to state
> conformance to protocols in an extension. Sometimes, the type will already
> implement some but not all of the protocol's requirements outside that
> extension because it is essential to the raison d'être of the type, and
> only the balance of the requirements would then be implemented in the
> extension that states conformance. It would be exceedingly unfortunate to
> forbid this pattern, which is both elegant and expressive, but OTOH it
> would be strange to have a method declare that it fulfills a requirement of
> a protocol to which, lexically, it had not yet been conformed.
>
> The declaration is only required on types for protocols which the type is
> known to implement at the file level. If some other code (even within the
> same module) extends a type to support a protocol, there is no requirement
> that previous methods had been documented as fulfilling that new protocol.
>
> In this sense, not every method which is mapped into a protocol may be
> marked as fulfilling a protocol, but the purpose isn’t to solve every
> corner case. If that were indeed the purpose, I could propose something
> much wordier where the extension has to declare that intent to expose
> existing methods as part of protocol conformance.
>
> > Lastly, it makes a very common task, that of conforming to a protocol,
> syntactically heavy. This is exacerbated when you consider that the scheme
> outlined here has the greatest benefit only when conformance to one
> protocol is concerned. When conforming to more than one protocol, a similar
> level of compiler help can only be obtained if you allow annotations as to
> which protocol's requirement is being fulfilled. To implement this
> additional syntax would be ludicrously heavy, but to ignore the issue would
> be failing to consider one major aspect of protocols: composability (as
> opposed to single inheritance). Again here, this is a critical difference
> from subclassing that makes adapting "override" (regardless of whether you
> choose a novel spelling) ineffectual.
>
> The purpose isn’t to map methods to protocols, but to clarify that a
> method exists to meet the requirements of a protocol. Without this, a
> simple typo (or redefinition of methods such as with the changes in Swift
> 3’s importer) causes what you thought was conforming to a protocol to
> either fail, or worse silently change behavior.


As I demonstrate above, there are other designs possible that do not
require source breakage, or even any new keywords, which recover
essentially all of the benefits you list here. Such alternative designs
would be opt-in, so those who care about this additional compiler help can
use it, and those who do not won't need to, consistent with Swift's new
emphasis on compatibility and its established emphasis on progressive
disclosure.

> Previous discussions on this topic have agreed that the developer
> experience of conforming a type to a protocol can be greatly improved, but
> the consensus has been that requiring a keyword to indicate protocol
> requirements is not the way to go about it. I too would love to see
> progress made on this issue, but having been previously an advocate for a
> solution similar to yours, the views of some very wise people have changed
> my thinking.
>
> There are often cases for the compiler to guess a developer’s intent to
> simplify syntax, but in this case I believe people are being bit by the
> compiler guessing incorrectly. If protocols didn’t make implementation of
> its requirements optional (via optional methods in objective-c, and
> protocol extensions in Swift) then there wouldn’t be a need to annotate
> methods to clarify intent. Given those features, I have trouble imagining a
> system where a compiler would be able to understand the developer’s intent
> and prevent issues without tagging protocol implementations in some manner.
>
> Unless I’m incorrect in my assumption that there compiler could only infer
> developer intent via some sort of method tagging, then it really is a
> decision whether clarity or terseness is more important in this scenario.
>
> -DW
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170218/41403390/attachment.html>


More information about the swift-evolution mailing list