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-6993] Swift imports @optional ObjC methods from superclass protocol as if implemented #49541
Comments
Comment by Daniel Jalkut (JIRA) I am working around the issue in my Swift code by checking whether the superclass's instances respond to the selector, rather querying super directly: if let superClass = self.superclass as? NSObject.Type {
if superClass.instancesRespond(to: #selector(NSApplicationDelegate.applicationWillTerminate(_:))) {
super.applicationWillTerminate(notification)
}
} |
Hmm. This used to go the other way, but I don't remember why we changed it. (Nor did we close the bug that was tracking the old behavior, rdar://problem/16127954.) @DougGregor, do you have the context here? |
Comment by Daniel Jalkut (JIRA) I feel like there are still some surprising behaviors here, but FWIW I guess I overlooked some nuances about the behavior of "respondsToSelector". The documentation indicates I should always be calling "instancesRespondToSelector" when checking super for conformance. |
This appears to be a special case of a bug I just filed (SR-7067) wherein it seems that the Swift compiler simply assumes that an Obj-C class implements all optional methods of protocols it conforms to. That said, you absolutely do need to still provide ¹I don't know when optional protocol methods changed from optionals to IUOs, but because of that, you can call such methods without checking for their existence. This seems like a really bad idea to me. |
@swift-ci create |
Okay, it looks like this is not a recent regression, but more likely a deliberate "least bad choice" from a past release to deal with wanting to call (Optional protocol methods are not IUOs, as discussed elsewhere. That's a code completion bug.) |
Attachment: Download
Environment
Version 9.3 beta (9Q98q)
macOS 10.13.3.
Additional Detail from JIRA
md5: ebc0717b07092dd0f64cd27c0152f061
is duplicated by:
relates to:
Issue Description:
If a Swift class inherits from an Objective-C class that conforms to a protocol with @optional methods, Swift assumes that the superclass in fact implements all the optional methods.
This has implications ranging from the unexpected requirement that the subclass label its own implementations of such methods as "override," to the failure of "super.responds(to: Selector)" to work as expected when calling through to a superclass.
Open the attached project to see a concise example: AppDelegate.swift implements a class AppDelegate that inherits from ObjC SuperDelegate. SuperDelegate conforms to the "MaybeSo" protocol but doesn't implement its only optional method: -doSomething.
When you build and run this example, you can see that no warnings or errors are received, and at runtime when AppDelegate.doSomething() attempts to test super's implementation of doSomething, it is assured that it does implement the method, so it calls through and raises an exception.
The real-life scenario I ran into this in was for an AppDelegate class in Swift that inherits from an Objective-C class that conforms to NSApplicationDelegate. In this scenario, the AppDelegate in Swift implemented applicationWillTerminate: and tried to call through to super.applicationDidTerminate only if it is implemented.
To continue experimenting with this bug, try moving NSApplicationDelegate conformance from the Swift AppDelegate to the ObjC SuperDelegate. Now you will be forced by Swift to use the "override" keyword on AppDelegate's implementation of applicationWillTerminate.
The text was updated successfully, but these errors were encountered: