[swift-evolution] SR-104: Improve Crash-Safety when Importing Objective-C Code Without Nullability Attributes
Fabian.Ehrentraud at willhaben.at
Sat Dec 12 16:54:29 CST 2015
Am 12.12.2015 um 21:34 schrieb Douglas Gregor <dgregor at apple.com<mailto:dgregor at apple.com>>:
Sent from my iPhone
On Dec 12, 2015, at 1:13 AM, Fabian Ehrentraud <Fabian.Ehrentraud at willhaben.at<mailto:Fabian.Ehrentraud at willhaben.at>> wrote:
Am 12.12.2015 um 06:03 schrieb Douglas Gregor <dgregor at apple.com<mailto:dgregor at apple.com>>:
On Dec 11, 2015, at 12:08 AM, Fabian Ehrentraud <Fabian.Ehrentraud at willhaben.at<mailto:Fabian.Ehrentraud at willhaben.at>> wrote:
On 10.12.2015, at 23:28, Douglas Gregor <dgregor at apple.com<mailto:dgregor at apple.com>> wrote:
On Dec 10, 2015, at 1:22 PM, Fabian Ehrentraud <Fabian.Ehrentraud at willhaben.at<mailto:Fabian.Ehrentraud at willhaben.at>> wrote:
Most of the implicitly unwrapped optionals we currently get from (Objective-)C APIs can, in fact, never be nil. Forcing programmers to deal with all of these values as full optionals leads to a ton of optional-related boilerplate that doesn’t actual help users write better code. Rather, it dilutes the effectiveness of optionals as a language feature: optionals should mean “nil matters here, think about it carefully!”. But if some large number of optionals people deal with on a day-to-day basis are instead “the compiler didn’t know, so you have to write !”, the useful meaning of the “true” optionals gets lost in the noise.
I think exactly the opposite. If an API has not yet been audited, the client needs to consult the documentation if a return value can ever be nil. If not, she might explicitly and knowingly unwrap the value safely or non-safely. I deem this a good thing, as it prevents unknowingly unsafe use. I do not think that it would get in the way, as the syntactic sugar for Optionals is quite minimal. Also when the API gets audited for nullability later on, the compiler will hint which optional unwrappings have been rendered unnecessary.
You’re discounting my main argument, which is that the safety provided by optionals is contingent on the nil case being interesting most of the time. That’s generally true in “pure” Swift code—Swift programmers use optionals when nil matters—and it’s generally true in imported (Objective-)C code that has been audited, but your change would create a lot of optionals where “nil” isn’t actually interesting in practice.
Have I understood it right that your argument is that defaulting to Optionals would would make them loose their meaning and result in programmers just use ! too often, also in cases where the nil case should properly be handled? I see the point. And I'm thankful for this constructive discussion.
Nonetheless I think that Swift preventing unintentional mistakes would be something to strive for. Have you got alternative ideas on how to deal with the issue this proposal tries to address?
I honestly don’t have alternative ideas here—implicitly unwrapped optionals is the best solution that we could find to balance the goals of making it easy to write correct code vs. not pushing too much boilerplate on users, and while I want to continue to make them less common in Swift, I don’t think changing the Clang importer is the right answer.
Would it be technically possible to have a different behavior for Cocoa APIs vs. own Application Code and integrated 3rd-party Frameworks?
Somewhat. One can distinguish between "system" and "user" frameworks.
Great. I guess restricting the change just to "user" frameworks would be a very good balance between safety and boilerplate.
The Cocoa API is pretty well documented, and I think IUOs don't hurt too much there, as opposed to the other two. Also if nullabillity annotations are missing from the latter two, they can be added. So the necessary boilerplate !/? would remind the users in a safe manner.
I'm unhappy with defaulting to IUOs as it has a bad impact on mixed projects. In pure ObjC it was expected that nil could be returned but mostly ignored as it could not hurt if methods were called on it, so not too many crashes arose. In a pure Swift project one can stay away from IUOs and avoid that nil issue alltogether if one stays away from forced unwrapping. But as soon as the two are used together, for example when migrating to Swift, crashes can be hidden in every line. And there are no compiler warnings, no analyzer inspections or anything that can help to find these lines.
That said, here is an alternative idea. A new compiler warning "Access to Objective-C method/function/property/initializer that misses nullability annotations". I guess this warning should not be shown for Cocoa APIs.
Would this result in even more work than the original proposal?
No, it's easier because warnings (especially opt-in ones) have far less impact on existing code. I think what you're asking for is a warning when implicitly unwrapping an IUO when we inferred the IUO from a lack of nullability information in the Objective-C API.
Yes excactly. I guess explicitly force unwrapping should not produce a warning, as it is obvious then that something unsafe happens.
It would be debatable if 2 separate warnings should be created, one for "system" and one for "user" frameworks.
For me, that's no longer even a language proposal: it's a smallish proposal for an opt-in warning.
Would it harm productivity if "Treat warnings as errors" is activated?
If it's opt-in or one can selectively downgrade it to a warning, it shouldn't harm productivity.
Especially together with "treat warnings as errors" the second proposal should provide approximately the same level of safety, or am I missing something?
As either proposal would help with the underlying issue, how should we proceed? Should I write down both variants in a single proposal and let the community decide in the review?
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution