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

ilya ilya.nikokoshev at gmail.com
Mon Dec 7 15:48:06 CST 2015


Yes, I read the article, even after I replied correctly to the "If yes, and
you understand why, congratulations; you don’t need to read any further."
challenge :)

> Remove all methods from P1 and P2, so that something() and another()
appear only in extensions.

Nope, I still don't see any problem:

protocol P1 {}
protocol P2 {}

extension P1 {

    func something() -> Int {
        return 1
    }

    func another() -> Int {
        return 1
    }
}

extension P2 {

    func something() -> Int {
        return 2
    }

    func another() -> Int {
        return 2
    }
}

class C1: P1, P2 {

    func something() -> Int {
        return 0
    }

}

C1().something() // class implementation, works as is
// C1().another() - ambigous, doesn't compile


PS I noticed you replied to me personally, perhaps it's a good idea to copy
to the list back.


On Tue, Dec 8, 2015 at 12:40 AM, Paul Cantrell <cantrell at pobox.com> wrote:

> Remove all methods from P1 and P2, so that something() and another()
> appear only in extensions.
>
> Did you read Alexandros’s article I linked to in the OP? That’s the place
> to start.
>
> P
>
> On Dec 7, 2015, at 2:52 PM, ilya <ilya.nikokoshev at gmail.com> wrote:
>
> Could you provide an example? I tried playing with protocol extensions,
> modelling this situation:
>
> > If an extension method collision occurs when a type implements multiple
> protocols,
>
> but so far all examples I found where one would see a collision are
> disallowed by compiler, e.g.
>
>
> protocol P1 {
>     func something() -> Int
> }
>
> protocol P2 {
>     func something() -> Int
>     func another() -> Int
> }
>
> extension P1 {
>
>     func something() -> Int {
>         return 1
>     }
>
>     func another() -> Int {
>         return 1
>     }
> }
>
> extension P2 {
>
>     func something() -> Int {
>         return 2
>     }
>
>     func another() -> Int {
>         return 2
>     }
> }
>
> class C1: P1 { // <- P1, P2 here doesn't compile
>
>     func something() -> Int {
>         return 0
>     }
>
> }
>
> class C2: P2 {
>
> }
>
> class C3: P1, P2 {
>
>     func something() -> Int {
>         return 0
>     }
>
>     func another() -> Int {
>         return 0
>     }
>
> }
>
> On Mon, Dec 7, 2015 at 7:17 AM, 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
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151208/128309cc/attachment.html>


More information about the swift-evolution mailing list