Open swift-ci opened 6 years ago
Comment by Marc Palmer (JIRA)
Here's another concrete use case where type inference breaks this and leads to unexpected behaviour:
protocol Feature {
static var parent: Feature.Type? { get }
}
extension Feature {
static var parent: Feature.Type? { return nil }
}
class MyFeature: Feature {
public static let parent = RemoteControlFeature.self
}
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.
class MyFeature: Feature {
public static let parent: Feature.Type? = RemoteControlFeature.self
}
Comment by Marc Palmer (JIRA)
The above actually means you cannot use type inference at all for properties where the property is optional and has an extension implementing it
Environment
Xcode 9.2 GMAdditional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 1273b80bd7c1605a99edfd258f9430bdIssue 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.