[swift-evolution] Static Dispatch Pitfalls

Goffredo Marocchi panajev at gmail.com
Sun May 22 03:42:17 CDT 2016


Sent from my iPhone

> On 22 May 2016, at 07:03, Vladimir.S via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I support *at least* to introduce such a special marker for method declared *only* in protocol extension (no declaration for it in protocol itself) to make it clear that it will be dispatched statically.
> Probably right now I support `nondynamic`.
> 
> But, there is question regarding another situation when the protocol method dispatched *statically* even if *defined* in protocol declaration:
> 
> protocol A {
>    func f()
>    func x()
> }
> 
> extension A {
>    func x() {print("a-x")}
> }
> 
> class B: A { // already strange. B depends on A extension. did not implement all required methods from A
>    func f() {}
> }
> 
> class C: B {
>    func x(){print("c-x")}
> }
> 
> var c : A = C()
> c.x() // "a-x". but C() *implements* x() that *is* defined in protocol
> 
> IMO this is totally unexpected and must be dispatched dynamically. I believe that there can not be any explanation why this is correct: A - is a protocol, C - is a class conformed to A protocol and implemented all methods of that protocol.
> 
> It is clear, that you don't want to decorate A.x() with such `nondynamic` as if it was implemented in B - it will be dynamic:
> 
> class B: A {
>    func f() {}
>    func x(){print("b-x")}
> }
> 
> var b : A = B()
> b.x() // "b-x". now dynamic
> 
> So, again, IMO  at least we need to decorate protocol extension methods that was not defined in protocol itself, but the 'issue' is bigger 'than just this.

Agreed, the issue is an important one of deterministic logical behaviour. Especially with protocols which help us decouple behaviour from implementation of said behaviour, but not just with protocols, there should not be a case in which depending on the type of the reference used you call a method or another.

If an instance implements a method and said method is called on said instance the instead implementation should execute no matter the type of the reference we are accessing it by. Message dispatching in Objective-C got this right. 

I do not think always dynamic dispatching/runtime message sending is not inherently unsafe/bad... and I am willing to trade off some of the extra automagic safety for the flexibility and predictability it can bring when used well. Without multiple inheritance and default methods/code in protocols, it is easier to tame the beast and have a working design in my opinion.

> 
>> On 21.05.2016 16:27, Matthew Johnson via swift-evolution wrote:
>> Nobody is talking about forcing them final.  We are talking about
>> annotating them with a keyword that documents their behavior (which is
>> unintuitive for sure but makes sense when you think through how things
>> work behind the scenes).
>> 
>> Maybe we will figure out a way to have something better in the future,
>> but until then highlighting the behavior via annotation is a pretty good
>> option.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


More information about the swift-evolution mailing list