New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-7940] "Ambiguous use" in Xcode 10, Swift 4.2 #50475
Comments
Comment by Anton Schukin (JIRA) @bob-wilson Thank you for your help on the lab session. |
You're welcome – thank you for the bug report |
@swift-ci create |
In Swift 4.2 some of the rules around ambiguous member references were tightened up. Note that in 4.1, it was already ambiguous to reference a method in this manner:
If the class already provides the requirements of the protocol, you should make the class conform to the protocol, and not use a subclass existential. Only use a subclass existential if the class does not actually implement the protocol. |
Comment by Anton Schukin (JIRA) @slavapestov So, basically, if a protocol defines a function or variable that matches a function or variable from existential class I have no other choice but make this class conform to the protocol and provide default implementation and then override it in subclasses. This way doesn't give necessary compile time checks as you may forget to override default implementation. Before compiler guaranteed that I can't put an object of a base class (because it doesn't conform to a protocol) or subclass that doesn't conform to a protocol into a variable. So, I could only put an object of a subclass that conforms to a protocol. Consider next example with protocols: protocol Protocol {
func function()
}
protocol AnotherProtocol {
func function()
}
class Impl: AnotherProtocol, Protocol {
func function() {}
}
var t: AnotherProtocol & Protocol = Impl()
t.function() This code doesn't produce an error. For me those two cases are similar and I would expect the same behaviour. |
> So, basically, if a protocol defines a function or variable that matches a function or variable from existential class I have no other choice but make this class conform to the protocol and provide default implementation and then override it in subclasses. Either the class provides implementations of those requirements, in which case it conforms to the protocol, or it doesn't, in which case you don't need to provide a default either. > This code doesn't produce an error. For me those two cases are similar and I would expect the same behaviour. The ambiguity was already diagnosed in 4.1 for methods; the new behavior in 4.2 is more consistent, just not in the direction you expect. Suppose both the protocol and the class define a method with the same name; which one would you expect member access to pick on a subclass existential value, and why? |
Comment by Anton Schukin (JIRA) — Either the class provides implementations of those requirements, in which case it conforms to the protocol, or it doesn't, in which case you don't need to provide a default either. In the second case I have a compilation error as in the example due to a variable with the same name in a protocol and in a base class. I would like to add that a protocol may contain more variables that don't overlap with variables from a base class and exist only in subclasses that conforms to the protocol. — Suppose both the protocol and the class define a method with the same name; which one would you expect member access to pick on a subclass existential value, and why? I thought that "MyClass & MyProtocol" declaration means "any MyClass that conforms to MyProtocol". So a type with this declaration already adopts MyProtocol (either through .extension to MyClass or in subclasses). In this way I see no ambuigity. But I suppose that I don't see the whole picture and I may be wrong about it. |
Comment by Anton Schukin (JIRA) @slavapestov I checked another example, with generics. It also have an ambiguous error: class Class {
let property: Int = 0
}
protocol Protocol {
var property: Int { get }
}
class Generic<T> where T: Class, T: Protocol {
var a: T
init(a: T) {
print(a.property)
}
} I suppose, this is expected. Thank you for clarification. |
Attachment: Download
Environment
Xcode 10 beta (10L176w)
Swift 4.2
Additional Detail from JIRA
md5: 55eeb487df67c567d097cb4bc9282854
is duplicated by:
Issue Description:
In Xcode 10 code in the attached playground compiling with error "Ambiguous use of ...".
A diagnostic report doesn't contain much information. A compiler produces an error when an object type is a combination of class and protocol types and a property of that object that is declared in both types is accessed.
Not sure is it a bug or intentional change. It worked before in Xcode 9.3 and Swift 4.1
The text was updated successfully, but these errors were encountered: