# SE-0217 - The "Unwrap or Die" operator

**URL:** <https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107>\
**Category:** Proposal Reviews\
**Created:** [June 29, 2018, 11:58pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107 "2018-06-29T23:58:37Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [June 30, 2018, 8:14pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/21 "2018-06-30T20:14:35Z")

</div>

An expansion of `??` to accept a `Never` on the right-hand-side will not work. On the surface it looks appealing:

```
let value = someOptionalValue ?? preconditionFailure("Must be non-nil")

```

However, this falls apart in various compilation modes when `someOptionalValue` is `nil`:

- `-Onone`: correctly emits the error message
- `-O`: crashes, but without an error message
- `-Ounchecked`: does not crash
- `-Osize`: crashes, but without an error message

One of the major points of this proposal is to get clearer diagnostics when things _do_ crash, which means you need reliability that it _will_ crash, and if it crashes, you need to guarantee that the crash reason will be there. Allowing `??` to accept a `Never` on the right hand side does not meet this criteria, because there are certain `Never`-returning functions that the compiler will just straight-up eliminate.

Only `fatalError()` meets the requirement for the combination of "always crash and always produce the diagnostic message". However, since there isn't a way to indicate that `??` would only want `fatalError()` on the right-hand size, it is not a feasible course of action.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [June 30, 2018, 8:31pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/22 "2018-06-30T20:31:11Z")

</div>

This sounds to me like we need a more general way to `panic()` since fatalError and friends won’t cut it.

---

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [June 30, 2018, 8:36pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/23 "2018-06-30T20:36:01Z")

</div>

`fatalError()` is the only "crashing" function that will always execute and always emit its error message, regardless of compilation mode.

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [June 30, 2018, 8:37pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/24 "2018-06-30T20:37:19Z")

</div>

Do we have information on the number of significant Swift projects which have defined their own “unwrap or die” operator? How about coding standards that recommend its use?

This has been discussed on Swift Evolution for long enough to be well known, meaning that if prominent developers / project leads found it beneficial then they would have already implemented and instituted it “in the wild”.

Since “unwrap or die” is simply syntactic sugar which can already be created by anyone who wants it, I would conclude that if it has not gained traction and entered common use on its own then it should not be added to the standard library.

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [June 30, 2018, 8:37pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/25 "2018-06-30T20:37:44Z")

</div>

This seems like a bug. I don't believe `fatalError ` is supposed to optimize out like that.

---

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [June 30, 2018, 8:38pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/26 "2018-06-30T20:38:12Z")

</div>

It doesn't; I was testing with `preconditionFailure` to illustrate the inconsistency in accepting any `Never`-returning function.

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [June 30, 2018, 8:40pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/27 "2018-06-30T20:40:10Z")

</div>

Yeah, but that's a deliberate design choice of `preconditionFailure` and `assertionFailure`. This problem pops up anywhere you use them, and has nothing to do with whether using `?? ` with `Never` is a good idea or not.

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [June 30, 2018, 8:52pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/28 "2018-06-30T20:52:26Z")

</div>

The optimization-mode behavior of `preconditionFailure` is irrelevant. This is still valid code, regardless of which `-O` flag you compile with:

```swift
guard let value = optionalValue else {
  preconditionFailure("optionalValue was nil")
}

```

Since `preconditionFailure` returns `Never` _according to the type system_, it is permitted to be the final statement in a `guard` block, and as such it would also be acceptable on the right hand side of a hypothetical `??` operator that takes a `Never`.

The documentation for `preconditionFailure` says:

> [@](#):
>
> In `-Ounchecked` builds, the optimizer may assume that this function is never called. Failure to satisfy that assumption is a serious programming error.

Meaning that it would be _programmer error_ to place it on the right hand side of a `??` whose left-hand side was nil, just as it is programmer error _today_ to place it in a `guard` block that fails.

---

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [June 30, 2018, 8:57pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/29 "2018-06-30T20:57:22Z")

</div>

Yes, it's valid code. However, the point of the proposal is to improve diagnostics and code expressivity, and allowing `preconditionFailure` in this manner means you'd be missing out on the "improved diagnostics" goal.

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [June 30, 2018, 8:59pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/30 "2018-06-30T20:59:42Z")

</div>

If someone chooses to build with `-Ounchecked`, they are making the _conscious decision_ to lose such diagnostics if they use `preconditionFailure`, because that's the documented behavior of that function. They are saying "this will never execute, I guarantee it, and if it does, I screwed up." If they want the diagnostic, they should use `fatalError`, or some other logging function of their own choosing that guarantees termination.

You can't hold `preconditionFailure` to a different standard if it's in an hypothetical `??` expression or in a `guard` statement.

---

<div class="post-metadata">

**Author:** ![ethanjdiamond](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ethanjdiamond/32/2353_2.png) [@ethanjdiamond](https://forums.swift.org/u/ethanjdiamond)\
**Post date:** [June 30, 2018, 9:08pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/31 "2018-06-30T21:08:31Z")

</div>

-1 on the !! syntax.

> [@gwendal.roue](#):
>
> wrappedValue ?? fatalError("missing value")

+1 on this syntax.

---

<div class="post-metadata">

**Author:** ![hlovatt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hlovatt/32/3044_2.png) [@hlovatt](https://forums.swift.org/u/hlovatt)\
**Post date:** [June 30, 2018, 9:47pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/32 "2018-06-30T21:47:01Z")

</div>

> [@Joe\_Groff](#):
>
> - What is your evaluation of the proposal?

+1 but with modifications. I would suggest:

1. `?? Never` overload be added, as suggested by others in this discussion.
2. `!! “...”` is a shortcut for `?? fatalError(“...”)`.

> [@Joe\_Groff](#):
>
> - Is the problem being addressed significant enough to warrant a change to Swift?

Yes, the use of `!` should be discouraged and the proposed fixit is a big improvement.

> [@Joe\_Groff](#):
>
> - Does this proposal fit well with the feel and direction of Swift?

I think it reads very naturally and will be easy to explain.

> [@Joe\_Groff](#):
>
> - If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

No

> [@Joe\_Groff](#):
>
> - How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Followed the original thread, followed this thread, and read the proposal.

---

<div class="post-metadata">

**Author:** ![riley](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/riley/32/7380_2.png) [@riley](https://forums.swift.org/u/riley)\
**Post date:** [June 30, 2018, 10:43pm UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/33 "2018-06-30T22:43:00Z")

</div>

I’m very much a +1. I find it unfortunate that there seems to be a strong opinion by many that force unwrapping should never be used, because I often use force unwrappings as assertions of program state to give me assurance I won’t accidentally mask bugs. With this proposal, the comments I normally write above these force unwrappings will appear in any crash logs, which is incredible useful.

As an aside, I do _not_ think using `myOptional ?? fatalError()` is a good alternative. I consider ?? to be a “safe” operator to ensure the program _won’t_ crash, and pairing it with fatalError would make the code harder to understand at first glance (especially when assigning an optional to another variable....that just seems incredibly strange).

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [July 1, 2018, 12:27am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/34 "2018-07-01T00:27:04Z")

</div>

> [@riley](#):
>
> I do _not_ think using `myOptional ?? fatalError()` is a good alternative. I consider ?? to be a “safe” operator to ensure the program _won’t_ crash, and pairing it with fatalError would make the code harder to understand at first glance (especially when assigning an optional to another variable....that just seems incredibly strange).

This statement would hold if ?? only accepted literals but we are allowed to call a function in which case all bets are off on how safe that func will be.

```swift

var some:String? = nil
func `safeFunc`<T>() -> T {
    fatalError("oops")
}

let boom = some ?? safeFunc()

```

---

<div class="post-metadata">

**Author:** ![Erica\_Sadun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/erica_sadun/32/243_2.png) [@Erica\_Sadun](https://forums.swift.org/u/Erica_Sadun)\
**Post date:** [July 1, 2018, 1:37am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/35 "2018-07-01T01:37:34Z")

</div>

### Preferring `??` to `!!`

If you read the proposal, you'll see that we discuss this as an option and explain that

> The new operator is consciously based on `!`, the unsafe forced unwrap operator, and not on `??`, the safe fallback nil-coalescing operator. Its symbology therefore follows `!` and not `?`.

Several people have brought up the option of using a `() -> Never` rhs with `??`, the nil-coalescing operator. This is highly problematic when using a rhs that is compiled away (`assert`, for example) in release builds.

Even if the team prefers to use a `() -> Never` rhs, I'd still recommend using `!!` over `??` to indicate the imbalance in roles between the safely unwrapped lhs and the unsafely unwrapped rhs. Expanding `Never` to be a bottom type _does not fix this symbology mismatch_. Whether `Never` is or is not a bottom type is orthogonal to this proposal.

### Writing the operator yourself in your own projects.

As in SE-0199, the counter to "write it yourself" is that Swift deserves nice things. This is a community-sourced evolution proposal, which exists in many dev environments. This operator:

- **Commonality** Applies across many problem domains and is a fundamental part of calling any nullable method
- **Readability** Enhances readability and produces run-time diagnostics in a way that comments cannot.
- **Consistency** Offers a consistent approach that encourages best-practice explanations of why an optional can never be `nil`.
- **Correctness** Moves unwrapping from use-sites to declaration-sites.

The core team wrote,

> The core team would welcome further proposals to fill in gaps like this in the standard library.

Our goal is to increase expressivity and enhance diagnostics. This operator is a nice thing. Swift developers deserve nice things.

### Function vs Operator

It feels natural to fit `!!` into the same use-space as `??` but provide for the situation where there can never be a fallback and the unwrap should never fail.

If the issue is "String" vs "Function", then `!!` can be followed by `() -> Never` adding a bit more verbosity (and the same issue of `assert`/etc being compiled away), but the spelling should be unsafe `!` and not safe `?`.

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [July 1, 2018, 1:59am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/36 "2018-07-01T01:59:38Z")

</div>

In previous phases of this proposal, I've favored the `??` + bottom `Never` alternative, because it gives us several different constructs like this. However, my thinking has evolved and I now support this proposal.

Instead of writing a lot of boring words about why this proposal is a good idea, I've prepared a visual aid:

 ![An expanding brain meme with the captions: "Force-unwrap is dangerous and should be banned by your style guide"; "You should force-unwrap only when there's no sensible thing to put in the guard's else block"; "You should always include a comment documenting why a force unwrap is safe"; "Build the comment into the language with unwrap or die"; "Force-unwrap is dangerous and should be banned by your style guide"](https://global.discourse-cdn.com/swift/original/2X/7/72ff6c254c0c6194dc0f87556b91c2d0c6c6a889.png)

Basically, I think that `!!` guides people into better use of force-unwraps. Merely asking people to "explain why this cannot be nil" may help people learn when a force-unwrap is appropriate and when they should do something else instead.

And that teaching advantage is one that `?? fatalError()` can't match. This is why my opinion on `!!` changed: Even if we supported `Never` values on the right side of `??`—and I still think we should!—the `!!` operator would still be a good idea purely as a shorthand for a best practice we very strongly recommend.

I have a couple of minor concerns:

- I'm worried that infix `!!` may look confusingly similar to infix `||`. One way to address this would be to change the operator to a single `!`; that would still be confusable with the `|` operator, but that one is used much less often. The parallel to `??` may be more important, though.

- The inability to point to the location of the error correctly is very disappointing. It's something we can try to improve later, though—and I can think of at least two ways to do it besides the proposal's suggestion, one much deeper and the other much hackier.

But despite these small issues, I think this proposal is a great idea and, if it's accepted, I expect to use it pretty often.

---

<div class="post-metadata">

**Author:** ![hlovatt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hlovatt/32/3044_2.png) [@hlovatt](https://forums.swift.org/u/hlovatt)\
**Post date:** [July 1, 2018, 4:28am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/38 "2018-07-01T04:28:36Z")

</div>

> [@Erica\_Sadun](#):
>
> Even if the team prefers to use a `() -> Never` rhs, I'd still recommend using `!!` over `??` to indicate the imbalance in roles between the safely unwrapped lhs and the unsafely unwrapped rhs.

Either spelling seems fine to me, i.e. I want a `() -> Never` rhs.

The issue of `assert` etc. getting optimised away is the same for any conditional execution of `assert` etc. and is therefore more a problem that `assert` etc. have than with `??` (or however it’s spelt).

---

<div class="post-metadata">

**Author:** ![timv](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/timv/32/13304_2.png) [@timv](https://forums.swift.org/u/timv)\
**Post date:** [July 1, 2018, 4:54am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/39 "2018-07-01T04:54:19Z")

</div>

For the record, `assertionFailure` does not have a return type of `Never` so putting it on the rhs of `??` won't even compile.

---

<div class="post-metadata">

**Author:** ![nh7a](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nh7a/32/1141_2.png) [@nh7a](https://forums.swift.org/u/nh7a)\
**Post date:** [July 1, 2018, 5:33am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/40 "2018-07-01T05:33:10Z")

</div>

Some people really prefer not to use force unwrap regardlessly and never ever go with 1 or 4 below, therefore go with 2 or 5. But they aren't better at all because 2 is too redundant for nothing and 5 isn't as clear as 4. For them, 4 and 6 work great because it's as concise as 1 and 4 while you don't have to use force unwrap.

I think we shouldn't encourage people to "hate" force unwrap but at the same time, I feel force unwrap is maybe like "goto"; it should probably better be discouraged to use until you really understand when to properly use it.

In that sense, I understand this proposal can be beneficial.

```swift
let url = URL(string: "https://example.com")! // 1
guard let url = URL(string: "https://example.com") else { fatalError("can't happen") } // 2
let url = URL(string: "https://example.com") !! "valid url" // 3

guard error == nil else { throw error! } // 4
if let e = error { throw e } // 5
guard error == nil else { throw error !! "valid error" } // 6

```

---

<div class="post-metadata">

**Author:** ![rxwei](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rxwei/32/664_2.png) [@rxwei](https://forums.swift.org/u/rxwei)\
**Post date:** [July 1, 2018, 6:51am UTC](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/41 "2018-07-01T06:51:43Z")

</div>

I'm generally +1 on this proposal. Here's my two cents:

A common pattern in interop code with legacy C API looks like the following.

```swift
// C API creating a status object.
let status = NewStatus()
// This C API returns a nullable pointer, but expects users to 
// check `status` first.
let value = someCAPI(status)
checkStatusAndDieOnFailure(status)
// Now, although `status` should guarantee that `value` is 
// non-null, we want to check it so that we don't have internal
// inconsistency errors.
guard let unwrappedValue = value else {
    fatalError("Status was success but the pointer is null!")
}
// Then use the non-null pointer.
return unwrappedValue

```

In this example, since `value` is a local variable, one can't write `guard let value = value` to shadow the optional value. Some pragmatists (though not me) would prefer to write the following because they feel that coming up with a new variable name is hard and cumbersome.

```swift
guard value != nil else { 
    fatalError("Status was success but the pointer is null!")
}
return value!

```

The `!!` operator, or even the `??`+`Never` alternative, would define this problem away.

```swift
let value = someCAPI(status)
checkStatusAndDieOnFailure(status)
return value !! "Status was success but the pointer is null!"

```

My concern with the `??`+`Never` is that `??` strongly indicates "unwrapped or default value". Even if we make `Never` the bottom type, `fatalError()` is **not** a default value. So I would prefer sticking with the exclamation mark.

I understand that making `!!` take an `@autoclosure () -> Never` could generalize the API a bit and allow custom fatal error crashers, it's arguably a bit more complex for most cases. I'm indifferent, but we could have both at some point.

[Previous page](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107.md?page=1)

[Next page](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107.md?page=3)
