Resolved: Insert "!" is a bad fixit

In many cases, a forced unwrap, simply using !, is the right way to unwrap an optional value. The problem isn't with ! existing or being used in code, especially when it's established that an optional cannot be nil at the point of ! use. The problem is that the compiler is guiding newer users down a path of using ! in an extremely unsafe way because it cannot contextualize the ! with regards to developer intent.

New users, who may be unfamiliar with guard let and if let, which provide exit patterns and conditional binding of unwrapped values, are stuck in the mode of "what do I need to do to make this code compile?" Stack Overflow, the dev forums, IRC, various slacks, etc are overflowing with examples of terrible ! use. Those of us who mentor and teach see reflexive ! insertion "just to make things work" propagate because of the fixit availability.

This is not a reflection of ! being an antipattern. This is due to a problem with compiler tooling and specifically the "moral hazard" of its fixit.

I personally want to introduce !! the unwrap or die operator, which asserts that an item cannot be nil and then provides a succinct in-code reason why the optional must be .some. Using !! creates better in-context documentation at the point of use both for experienced and naive users.

In addition experienced users can always use ! because it is and will continue to be an important part of the Swift programming language.

I don't want this thread to be a referendum on "Should I eschew ! in my code?". You shouldn't. The points I'm posing are these:

  • The Swift compiler lacks a holistic understanding of developer intent.
  • The ! fixit should not be used as a bandaid to make things compile.
  • Experienced developers can distinguish whether an unwrapped value reflects an overlooked unwrap or it is guaranteed to never contain nil.
  • Inexperienced developers, unless they're moving from a language with similar constructs, usually will not. They're focused on getting past a compilation barrier, without realizing the hazard of nil values at the point of use.
  • The fixit is a modest courtesy for experienced developers.
  • The fixit is a moral hazard for inexperienced developers.

Given Swift in its current form, the choices that should be considered are:

  1. Removing the fixit entirely but retaining the information in the error message.
  2. Removing the fixit and retooling the error message to offer a link to optional best-use tutorials.
  3. Offering a better fixit by adopting !!.

I don't think "overhauling the compiler to guess user intent" is on the table nor "remove ! from the programming language".

5 Likes