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
SR-6613 Warn when shadowing an instance variable with a local variable
SR-6636 Constant and Variable shadowing produces confusing Program Bugs
SR-1420 Provide compiler warning when shadowing generic type
SR-1841 QoI: Warn when shadowing generic type parameters
SR-3496 Silent parameter shadowing is a source of subtle, hard to spot bugs
Issue Description:
Consider the following code:
/// An object managed by some framework in use/// The key paths point to the properties the framework manages/// The name key path is optional, the framework won't bother if it's nilpublicprotocolFrameworkManagedSprocket {
staticvarsprocketUUIDKey: WritableKeyPath<Self, UUID> { get }
staticvarsprocketNameKey: WritableKeyPath<Self, String>? { get }
}
extensionFrameworkManagedSprocket {
staticvarsprocketNameKey: WritableKeyPath<Self, String>? { returnnil }
internalvar_frameworkSpcketUUID: UUID {
get { returnself[keyPath: Self.sprocketUUIDKey] }
set { self[keyPath: Self.sprocketUUIDKey] = newValue }
}
internalvar_frameworkSprocketName: String? {
get { returnSelf.sprocketNameKey.map { self[keyPath: $0 } }
set { ifletk = Self.sprocketNameKey { self[keyPath: k] = newValue! } }
}
}
If it were desirable to force a given set of conforming objects to always have a name if they also conformed to some other protocol, one might try this:
publicprotocolFrameworkManagedWidget: FrameworkManagedSprocket {
staticvarsprocketNameKey: WritableKeyPath<Self, String> { get }
}
Unfortunately, this does not have the desired effect:
The non-optional version of the name key path shadows the optional version; it is no longer possible to access the optional version in any structure that conforms to the "widget" protocol, while the accessors for the original "sprocket" protocol still access only the optional version. The compiler never emits any errors or warnings of any kind for this usage.
This leads to very subtle and difficult-to-trace bugs for anyone unfamiliar with these semantics or the codebase in use. While this example is definitely contrived in order to show how easy it is to create such an issue by mistake, several instances of this behavior appear in the wild; there is likely to be code which even unwittingly depends on this confusing behavior.
Like the many other forms of shadowing mentioned in other bugs, this seems worthy of, at the very least, a warning from the compiler that access to the original property (and any value it may have acquired by protocol extension or otherwise) has been lost.
The text was updated successfully, but these errors were encountered:
Notably, this can happen through "sideways" shadowing as well as direct inheritance:
protocolFrameworkManagedWidget{// does not require conformance to SprocketstaticvarsprocketNameKey:WritableKeyPath<Self,String>{get}}
The same result is seen in this variation - the Sprocket version of the keypath is silently shadowed.
Worse, if there is no default implementation for either version of the keypath (e.g. if there were no extension of the Sprocket protocol), the MyWidget class becomes impossible to compile; it can only conform to one of the conflicting declarations for sprocketNameKey at a time. In this event it reduces to a case of poor compiler diagnostics - the compiler will helpfully say "Type does not conform to protocol" for one or the other protocol, and proceed to offer a fixit that creates protocol stubs that themselves don't compile, rather than diagnosing that the two protocols are mutually incompatible.
Additional Detail from JIRA
md5: ac3d620179bbdcdd2af52327cd39dbbe
relates to:
Issue Description:
Consider the following code:
If it were desirable to force a given set of conforming objects to always have a name if they also conformed to some other protocol, one might try this:
Unfortunately, this does not have the desired effect:
The non-optional version of the name key path shadows the optional version; it is no longer possible to access the optional version in any structure that conforms to the "widget" protocol, while the accessors for the original "sprocket" protocol still access only the optional version. The compiler never emits any errors or warnings of any kind for this usage.
This leads to very subtle and difficult-to-trace bugs for anyone unfamiliar with these semantics or the codebase in use. While this example is definitely contrived in order to show how easy it is to create such an issue by mistake, several instances of this behavior appear in the wild; there is likely to be code which even unwittingly depends on this confusing behavior.
Like the many other forms of shadowing mentioned in other bugs, this seems worthy of, at the very least, a warning from the compiler that access to the original property (and any value it may have acquired by protocol extension or otherwise) has been lost.
The text was updated successfully, but these errors were encountered: