protocol P1 {
var foo: Double { get }
}
protocol P2 {
var foo: String { get }
}
it is allowed to refer to the existential protocol type P1 & P2, even though it shouldn't be possible.
In theory we should have
(P1 & P2).self == Never.self
since foo's type has to be "Double & String", which is not possible.
func bar<T: P1 & P2>(_ x: T) {
x.foo // suggested as of type Double in autocompletion
// shown as of type String in the Quick Help pop-up
}
Of course, no concrete type can conform to P1 & P2 so the bar function can never be called.
However, I'm wondering if the compiler should consider T == Never to prevent foo from being suggested at all.
There isn't a public way to disambiguate, but P1.foo and P2.foo are distinct, and a type can conform to both protocols (the following code compiles using an undocumented feature):
protocol P1 {
var foo: Double { get }
}
protocol P2 {
var foo: String { get }
}
struct S: P1 {
var foo: Double { 42 }
}
extension S: P2 {
@_implements(P2, foo)
var bar: String { "Hello" }
}
let p2: P2 = S()
print(p2.foo) // "Hello"
[Edit: or see @michelf's demonstration with default implementations]
Imho the "cleaner" solution would be to allow a type to have both properties. It might be weird, and it probably should be avoided — but it has always(?) been valid for methods.
You’ve been misled here: foo is not of any existential type, and the interface is incorrect to suggest that E1 & E2 is the inferred type (it is not; the type is T.A). This would be worth filing a bug.
In the first three examples, typing x in the function body suggests x: Collection, x: P1 & P2 and x: P1 & P2 respectively, i.e. x's conformances instead of its type. Should it be filed as a bug?
Sounds similar to how some collection's Index is often referred to by the autocomplete interface as just Comparable (which is usually not the information I'm interested in at that moment).