[swift-evolution] [Discussion]: Deprecate !-Unwrapping of Optionals

Brent Royal-Gordon brent at architechies.com
Mon Feb 29 02:40:18 CST 2016

> Because of the above, I'd like to start a discussion about its deprecation and eventual removal in favor of either an unsafeUnwrap function or other extra-syntactic constructs.  I don't intend for force-unwrapping as a concept to go away, as there will always be corner cases where it is necessary, but I don't believe it deserves to be so easy to do in a language that holds safety as a core tenant.

I could not disagree more strongly.

Swift takes the position that assertions are good and that it's better to crash in an unexpected state than to limp on. Force unwrapping is an example of that philosophy. A force unwrap is a "this is not nil" assertion.

That assertion often is not appropriate—namely, in code that tests for `nil`—and so we provide, by my count, five general ways to test-and-use nils (pattern matching, optional binding, optional chaining, defaulting, and mapping) without force unwrapping. These features are all great and, with *very* few exceptions, you should always use one of them rather than test-and-force-unwrap.

But where it *is* appropriate to assert non-nil, *we want you to force unwrap*. If, as you write your code, you are certain a value cannot be nil, we want your code to say so. That way, the code will crash if you're wrong, at the exact point where you made the mistake, where the problem will be easiest to diagnose. We do *not* want you to use a test-and-use construct in a place where you believe the test will always succeed, because you will probably not give any particular attention to the test-failed behavior, so it will probably be wrong.

In other words, making force unwrapping more difficult will not make people correctly handle unexpected nils—it will make them write code that *undetectably* does the wrong thing by skipping code that wasn't actually meant to be skipped. You'll see fewer crashes but more bugs. That runs counter to Swift's formulation of safety, and I think it would be a serious mistake.

I recently had the pleasure of debugging some force unwrap crashes in a view controller I hadn't touched in a while. The force unwraps I used very quickly demonstrated to me that my ideas about the code's lifecycle were wrong: for instance, I thought it would never be called before a certain property was set, but it turned out it sometimes was. If I had used a conditional construct without thinking through the consequences, that would have manifested as a mysteriously empty menu which I would have had trouble debugging. By stating explicitly in my code that I believed those values could not be nil, Swift quickly disproved my belief, showed me exactly what was wrong, and prompted me to correct it. That's the best thing it could have done for me in this situation.

I often see Swift style guides suggest that force-unwrapping is a strong code smell and should always be avoided, but I think that's wrongheaded. Test-and-force-unwrap *is* a code smell, and force-unwrap-when-you're-not-really-sure is incorrect too. But when you *are* sure, force unwrap is the very best way to write your code, because it will make any mistakes immediately obvious.

That's a feature, not a bug.

Brent Royal-Gordon

More information about the swift-evolution mailing list