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

ilya ilya.nikokoshev at gmail.com
Mon Dec 7 16:18:12 CST 2015


On Tue, Dec 8, 2015 at 1:11 AM, Kevin Ballard via swift-evolution <
swift-evolution at swift.org> wrote:

> I'd love to see these two key things that Joe mentioned get added.
> Diagnostics around confusing situations is a good idea (although there
> needs to be a way to disable it too; what if I intentionally need to use
> the same name in a type and in an extension to one of the conformed-to
> protocols, for various reasons?).
>
> I can't support the original proposal though, of making foo.bar() use
> dynamic dispatch. 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.
>
> It's also worth noting that the current behavior, where methods defined
> in protocol extensions can't be overridden by the implementing type, may
> actually be the desired behavior in many cases.


It is indeed the only logical choice; for example I could make a private
protocol extension - obviously, a class that has no access to it won't be
able to override it.


> Heck, the ability to
> trigger this different behavior is one of the three reasons to even
> define methods in protocol extensions instead of in the protocol (the
> others being when you're defining it for a subset of protocol
> implementations, and when you're defining extensions on protocols
> imported from other modules). Removing this functionality (by making
> foo.bar() always dynamic) means reverting back to the Swift 1.x
> convention of having global functions to provide this behavior.
>
> I wouldn't mind seeing something like the `dynamic` keyword to allow
> concrete types to override these protocol extension methods (although
>

You currently allow it by declaring method to be part of protocol, which
means that an entry for some method is reserved in the protocol witness
table. This entry will be filled either by concrete method, if present, or
by protocol default implementation.


> `dynamic` in this case would not imply @objc, like it does today, which
> may be a little confusing), but that would be opt-in behavior.
>
> -Kevin Ballard
>
> On Mon, Dec 7, 2015, at 12:14 PM, Joe Groff via swift-evolution wrote:
> > The main reason to constrain dynamic dispatch is modularity. The problems
> > of interfering categories or monkey-patches in languages like ObjC and
> > Ruby with late-bound dispatch and open classes are well-known. In Swift's
> > model, it isn't possible for an extension in one module to interfere with
> > existing protocol conformances or class hierarchies at runtime (except
> > with @objc of course). Modules need to be compiled together to be aware
> > of each other to interact with each other's interfaces.
> >
> > The particular example Alexandros brings up is more an artifact of our
> > existing implementation than desirable behavior. Two key things are
> > missing:
> >
> > - the ability for extensions to protocols to add new
> > dynamically-dispatched methods, and
> > - compiler quality work to diagnose confusing cases where concrete types
> > obviously shadow non-dynamic protocol extensions.
> >
> > There is a related behavior change proposal Doug Gregor's been working on
> > for classes, to have conforming to a protocol implicitly re-declare all
> > the protocol's methods as class methods, so that they can be overridden
> > by subclasses in the expected way.
> >
> > -Joe
> >
> > > On Dec 6, 2015, at 8:17 PM, Paul Cantrell via swift-evolution <
> swift-evolution at swift.org> wrote:
> > >
> > > One of the few things in Swift 2 that feels to me like a design flaw
> is the way Swift mixes static and dynamic method dispatch.
> > >
> > > Alexandros Salazar gives an excellent explanation of this problem —
> and I agree wholeheartedly with his title for the article:
> > >
> > >    http://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future
> > >
> > > The upshot is that when we see this:
> > >
> > >    foo.bar()
> > >
> > > …it’s very hard to know how the compiler will determine which
> implementation of bar() to use. It might use static dispatch; it might use
> dynamic dispatch.
> > >
> > > The rules that govern this are arcane, and hard to remember. They have
> the feeling of being a “gotcha” question for job interviews — always a red
> flag for language features.
> > >
> > > Even if you remember the rules, the information needed to determine
> whether dispatch is static or dynamic is hard to track down. It depends on
> whether bar()’s implementation comes from an extension, whether the
> extension method appeared on the extended protocol, and whether the
> inferred type of foo is the protocol itself or an implementing type.
> > >
> > > A crucial part of the meaning of “foo.bar()” is implicit, and hard to
> determine. This runs contrary to Swift’s stated goal of prioritizing
> clarity at the point of API use, and its general pattern of making intent
> explicit. And it feels dangerous — a wellspring of insidious bugs.
> > >
> > > Thus:
> > >
> > >
> > > PROPOSAL
> > >
> > > Make the syntax “foo.bar()” always use dynamic dispatch, i.e. always
> use _only_ the runtime type of foo to determine which implementation of
> bar() to use. If an extension method collision occurs when a type
> implements multiple protocols, require the type to explicitly specify which
> one to use (as Swift already requires the caller to do at the point of
> invocation).
> > >
> > >
> > > I mean this proposal somewhat as a strawman. It’s such an obvious
> choice, I’m sure there were good reasons not to do it. But I’d like to
> propose the obvious solution in order to understand what’s wrong with it. I
> realize static dispatch precludes some optimizations, but I doubt that this
> alone drove the design choice. I see no safety or expressiveness upside to
> the way it works now.
> > >
> > > Cheers,
> > >
> > > Paul
> > >
> > > _______________________________________________
> > > 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/20151208/2bcec9f9/attachment.html>


More information about the swift-evolution mailing list