Clashing protocol functions cannot be disambiguated

Originator:ivan
Number:rdar://17435540 Date Originated:2014-06-24
Status:Open Resolved:
Product:Xcode Product Version:Version 6.0 (6A216f)
Classification:Enhancement Reproducible:Always
 
Consider a class implementing two protocols with clashing function declarations (name + all parameter types). Currently there is no mechanism to disambiguate which function is being a) implemented and b) invoked. The compiler collapses the implementation of the clashing function to be invoked for both protocols even though these may have very different semantics (as function name *will* depend on the protocol context)

Regarding implementation, I propose that it's disambiguated with extensions. Allow the following:

protocol Protocol1 {
    func doSomething()
}

protocol Protocol2 {
    func doSomething()
}

//  Compiler error - don't know which one is being implemented, use extension for this.
class Class1 : Protocol1, Protocol2 {
    func doSomething() {
        println("which one is it?");
    }
}

//  Fine - the compiler knows that it's Protocol1 that's being implemented *and* it's obvious to the programmer as well.
class Class2 : Protocol1 {
    func doSomething() {
        println("it's protocol1");
    }
}

//  Fine - again it's perfectly clear to both compiler and programmer what's going on.
extension Class2 : Protocol2 {
    func doSomething() {
        println("it's protocol2");
    }
}

Regarding invocation the compiler knows that there is an ambigous call and it with explicit casting it's easy for the programmer to manually disambiguate:

var obj = Class2()
obj.doSomething()   //  Compiler error - it's not clear which function should be invoked, cast to explicit var var p1 = obj as Protocol1;
p1.doSomething()    //  Fine - invoke the Protocol1 implementation
var p2 = obj as Protocol2;
p2.doSomething()    //  Fine - invoke the Protocol2 implementation

This even works when extending classes to which we don't have source code:

//  In library source code (we don't have it)
protocol LibraryProtocol1 {
    func doSomething()
}

class LibraryClass : LibraryProtocol {
    func doSomething() {
        //  whatever it may be
    }

    func doSomethingConditionally() {
        if(someCondition) {
            doSomething()
        }
    }
}

protocol LibraryProtocol2 {
    func doSomething()
}

//  Our source code
extension LibraryClass : LibraryProtocol2 {
    func doSomething() {
        //  something else to be done
    }
}

var obj = LibraryClass()
obj.doSomethingConditionally()    //  Invokes LibraryProtocol1.doSomething() because when LibraryClass module was compiled there was no ambiguity
obj.doSomething()   //  Error - this now has to be disambiguated manually

Steps to reproduce:

1. Run this code in a playground:

protocol Protocol1 {
    func doSomething()
}

protocol Protocol2 {
    func doSomething()
}

class TestClass : Protocol1, Protocol2 {
    
    func doSomething() {
        println("which one is it?");
    }

}

var t = TestClass()
var p1 = t as Protocol1;
p1.doSomething()
var p2 = t as Protocol2;
p2.doSomething()

Expected results:

It shouldn't compile (clashing function declarations) and it should allow us to disambiguate the implementations

Actual results:

It compiles and prints out "which one is it?" two times.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!