You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a source of hard to find and potentially very dangerous bugs.
Take the following code:
protocolP {}
extensionP {
staticvarx: Int { return2 }
}
structS: P {
staticvarx = ""
}
// Outputs "S.x is: [], with type String"print("S.x is: [\(S.x)], with type \(type(of: S.x))")
letviaProtocol: P.Type = S.self// Outputs "S.x is: [2], with type Int"print("S.x is: [\(viaProtocol.x)], with type \(type(of: viaProtocol.x))")
The result is a type S with "two implementations" of x with different types, depending on how you access the property.
The compiler considers S to conform to P because of the protocol extension, but silently ignores the declaration specific to S which has a different type.
This results in different call sites in the app seeing entirely different values and due to static compilation and type safety, everything seems fine!
There appear to be two failings:
1. Extensions are deemed sufficient to satisfy protocol conformance, even if a Type provides its own value/implementation with a different type
2. The compiler permits redeclaration of a property with a different type, when there is an extension that already declares a different type for that property (in the case where the protocol does not have the property as a requirement)
Note that the above problem still happens even if P defines x as a requirement, which is even more surprising given that S redeclares it with a different type and the protocol is clearly mandating a different type.
UPDATE
This is even more pernicious if the difference in type is just optionality:
In this case, due to type inference the results can be particularly confusing depending on the context in which you access the property, with the compiler making choices for your based on the context and returning different values.
The text was updated successfully, but these errors were encountered:
This code compiles fine, but `parent` is nil when read from a `Feature.Type`. Relying on type inference has allowed it to appear to do the right thing but it has merely shadowed the extension's implementation. Explicitly typing the property solves this. This seems pretty bad as avoiding explicit typing is encouraged by Swift.
Environment
Xcode 9.2 GM
Additional Detail from JIRA
md5: 1273b80bd7c1605a99edfd258f9430bd
Issue Description:
This is a source of hard to find and potentially very dangerous bugs.
Take the following code:
The result is a type
S
with "two implementations" ofx
with different types, depending on how you access the property.The compiler considers
S
to conform toP
because of the protocol extension, but silently ignores the declaration specific toS
which has a different type.This results in different call sites in the app seeing entirely different values and due to static compilation and type safety, everything seems fine!
There appear to be two failings:
1. Extensions are deemed sufficient to satisfy protocol conformance, even if a Type provides its own value/implementation with a different type
2. The compiler permits redeclaration of a property with a different type, when there is an extension that already declares a different type for that property (in the case where the protocol does not have the property as a requirement)
Note that the above problem still happens even if
P
definesx
as a requirement, which is even more surprising given thatS
redeclares it with a different type and the protocol is clearly mandating a different type.UPDATE
This is even more pernicious if the difference in type is just optionality:
In this case, due to type inference the results can be particularly confusing depending on the context in which you access the property, with the compiler making choices for your based on the context and returning different values.
The text was updated successfully, but these errors were encountered: