[swift-evolution] Proposal: Universal dynamic dispatch for method calls

Kevin Ballard kevin at sb.org
Mon Dec 7 17:52:58 CST 2015

On Mon, Dec 7, 2015, at 02:51 PM, Paul Cantrell wrote:
> > The ability to use static dispatch in most cases is one of the great features of Swift, and it's something that needs to be preserved, not relegated to being an optimization that can be done occasionally.
> Can you think of a situation where that’s the desired semantics, as
> opposed to either a desirable optimization or a confusing workaround for
> the “monkey collision” problem? (I can’t see the use case, but I’m open
> to hearing it!)

Yes. Any time you're replacing a global function with a protocol
extension, to preserve the semantics the protocol extension's method
implementation must be called every time the call is resolved via the
protocol (e.g. with generics or protocol objects, as opposed to calling
it on a concrete type that just happens to implement the protocol). If
you want the method implementation to be overridden by the concrete
implementing type, then the method should be declared in the protocol
instead of just in a protocol extension. Whether or not you want these
semantics is entirely up to you and your particular use-case.

I also disagree with the claim that the current rules are confusing. I
think they're very straightforward. Whenever you call a method on a
protocol value (either a generic type that's bound by the protocol, or a
protocol object), the only question that matters for method resolution
is "was this method declared in the protocol?". If it was declared in
the protocol, then concrete implementations can override it. If it was
not declared in the protocol, then concrete implementations cannot
override it. And this is a good thing. If concrete implementations could
override methods that were only provided through protocol extensions,
then that's a great way to accidentally override methods without
realizing it. Or more generally, if I declare an extension on some
protocol with some method, subjecting that method to overriding would be
a serious hazard, because there's no real way for me to know whether any
implementing type ends up accidentally overriding the method (and if
they did, they may not match the behavior expected from my method). The
only sane behavior here is to not subject it to overriding by default.

Incidentally, I rather like ilya's suggestion of declaring another
protocol with conditional conformance as the solution for declaring an
overridable method in a protocol extension. That provides a good way of
having this behavior without changing the semantics of protocols, and
all it requires is to be able to combine `where` clauses with protocol
conformance (which is something that's already known to be desired on
types, e.g. so Optional can conform to Equatable when Wrapped:
Equatable, so the only change here is extending that to protocols).

-Kevin Ballard

More information about the swift-evolution mailing list