# Combining ? with throwing when there's no reasonable default

**URL:** <https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722>\
**Category:** Discussion\
**Created:** [February 20, 2019, 8:42pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722 "2019-02-20T20:42:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![reitzig](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/reitzig/32/2054_2.png) [@reitzig](https://forums.swift.org/u/reitzig)\
**Post date:** [February 20, 2019, 8:42pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/1 "2019-02-20T20:42:09Z")

</div>

If we want to say, "use this or if it's `nil`, that default", we can write:

```swift
let a = maybeA ?? A()

```

However, saying "use this or if it's `nil`, throw" is more verbose (if descriptive):

```swift
guard let a = maybeA else {
	throw SomeError()
}

```

One might imagine writing

```swift
let a = maybeA ?? throw SomeError()

```

but this doesn't work: `throw X` is a statement, not an expression, so it doesn't parse. As @Nevin [notes](https://forums.swift.org/t/elvis-operator/11368/12), we can make the right-hand side an explicit closure evaluation:

```swift
let a = try maybeA() ?? { throw SomeError() }()

```

This reads a little arcane, and the `try` feels both redundant and oddly placed.

Further, @Chris_Lattner3 [comments](https://forums.swift.org/t/elvis-operator/11368/13):

> That said, making that change wouldn't fix your code above, because ?? requires the left and right side to be the same base types, and Never is not an A.

This is a little odd -- arguably, `Never` is a natural candidate for a bottom type; see [here](https://forums.swift.org/t/pitch-never-as-a-bottom-type/5920) -- but prevents us from just definining `throw X` to be an expression of type Never.

What are other ways to express the above neatly?

* * *

For reference, this is valid Kotlin:

```kotlin
fun foo(a: String?) : Int {
    return a?.toIntOrNull() ?: throw RuntimeException()
}

```

[Kotlin's Elvis operator](https://kotlinlang.org/docs/reference/null-safety.html#elvis-operator) is similar to `??`, but (I think) `throw X` is an expression of type `Nothing` here, which _is_ the bottom type in Kotlin. So this type-checks (and even drives data flow analysis).

---

<div class="post-metadata">

**Author:** ![reitzig](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/reitzig/32/2054_2.png) [@reitzig](https://forums.swift.org/u/reitzig)\
**Post date:** [February 20, 2019, 8:47pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/2 "2019-02-20T20:47:37Z")

</div>

I guess the type checker could give special treatment to `throw X` expressions (which can't be confused with any other expression due to the keyword, I think) and make it attain any type "on demand". An implicit bottom type, if you will.

Doesn't sound like the value obtained justifies that kind of cost (new special cases in grammar and type checker), though.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 20, 2019, 9:21pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/3 "2019-02-20T21:21:53Z")

</div>

If this would go into stdlib I don‘t think it would require any magic or compiler support other than an overload that you can define on your own already.

```swift
infix func ?? <T>(lhs: T?, rhs: @autoclosure () -> Error) throws -> T

// usage
let a = try optional ?? SomeError()

```

---

<div class="post-metadata">

**Author:** ![Ponyboy47](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ponyboy47/32/2605_2.png) [@Ponyboy47](https://forums.swift.org/u/Ponyboy47)\
**Post date:** [February 20, 2019, 9:23pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/4 "2019-02-20T21:23:34Z")

</div>

This is possible through a simple extension:

```swift
infix operator ?!: NilCoalescingPrecedence

/// Unwrap or throw operator
public func ?! <T>(lhs: T?, rhs: @autoclosure () -> Error) throws -> T {
    if let val = lhs { return val }
    throw rhs()
}

```

Use it with:

```swift
let x = try optional ?! MyError()

```

---

<div class="post-metadata">

**Author:** ![suyashsrijan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/suyashsrijan/32/5292_2.png) [@suyashsrijan](https://forums.swift.org/u/suyashsrijan)\
**Post date:** [February 20, 2019, 9:27pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/5 "2019-02-20T21:27:53Z")

</div>

You can also just do `unwrapped ?? fatalError("This should never be nil")`, however throw would be nicer.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 20, 2019, 9:29pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/6 "2019-02-20T21:29:47Z")

</div>

If you change Error to Never then yes, otherwise we would need to wait until Never becomes the bottom type in Swift. That was proposed once by Erica Sudan but was rejected, I don‘t remember the reasons though.

Edit: Ah now that Never conforms to Error, this is also possible with a single overload yes, good catch.

---

<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:** [February 21, 2019, 2:34am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/7 "2019-02-21T02:34:37Z")

</div>

> [@reitzig](#):
>
> What are other ways to express the above neatly?

You can make a `throwError` function:

```swift
func throwError<T>(_ e: Error) throws -> T {
  throw(e)
}

```

And then use it:

```swift
let y = try x ?? throwError(SomeError())

```

• • •

You can also do something similar with `fatalError`:

```swift
func crash<💥>() -> 💥 { fatalError() }

```

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [February 21, 2019, 3:42am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/8 "2019-02-21T03:42:53Z")

</div>

I did actually originally have `throw` as an bottom expression, but I got grief over it and didn't care to push the issue. It seems like a reasonable thing to do.

I don't think we'd want to make arbitrary uninhabited types act like bottom in the type system; that would almost certainly do nasty things to the type-checker.

---

<div class="post-metadata">

**Author:** ![reitzig](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/reitzig/32/2054_2.png) [@reitzig](https://forums.swift.org/u/reitzig)\
**Post date:** [February 21, 2019, 10:29am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/10 "2019-02-21T10:29:21Z")

</div>

I like this variant. The `try` seems to be in the wrong place, but there isn't a good one for it, anyway.

---

<div class="post-metadata">

**Author:** ![reitzig](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/reitzig/32/2054_2.png) [@reitzig](https://forums.swift.org/u/reitzig)\
**Post date:** [February 21, 2019, 10:30am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/11 "2019-02-21T10:30:36Z")

</div>

So basically, if `throw` was a function instead of a keyword, it would already work? That may be an angle, but would probably break too much.

(Using untypable but descriptive characters for type parameters, nice!)

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 21, 2019, 10:31am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/12 "2019-02-21T10:31:04Z")

</div>

Try is in the correct place actually since the expression really is not different from:

```swift
let a = try (optional ?? SomeError())

```

---

<div class="post-metadata">

**Author:** ![reitzig](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/reitzig/32/2054_2.png) [@reitzig](https://forums.swift.org/u/reitzig)\
**Post date:** [February 21, 2019, 10:46am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/13 "2019-02-21T10:46:31Z")

</div>

Yes and no. While _correct_, it doesn't make much visual sense: the idea is that the rhs throws, but since we faked it by making `??` throw, the `try` has to go in front.  
In @Nevin's proposal, we could write (I think)

```swift
let y = x ?? (try throwError(SomeError()))

```

That is, the `try` would be where something can actually be thrown.

But then, a "native" implementation shouldn't require `try` at all, just like a `throw X` statement doesn't require one; it's _already_ explicit that and where we can throw.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 21, 2019, 11:00am UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/14 "2019-02-21T11:00:17Z")

</div>

I don't understand what you're trying to solve. If you cannot unwrap the value it's `??` that has to throw and you will need to handle the error in the same scope.

```swift
let y = x ?? (try throwError(SomeError()))

```

Does not make sense since you cannot assign anything to `y` if you cannot unwrap the value and it will only throw inside `??` anyway.

That means you want one the two possible overloads:

```swift
func ?? <T>(lhs: T?, rhs: @autoclosure () -> Error) throws -> T
func ?? <T>(lhs: T?, rhs: @autoclosure () throws -> Void) rethrows -> T

```

In case of the second overload we would need to teach the compiler to interpret `throw Error` as it would return `Void`, but even then you still would require `try`.

```swift
func ?? <T>(lhs: T?, rhs: @autoclosure () throws -> Void) rethrows -> T {
  if let result = lhs { return result }
  try rhs()
  fatalError("Cannot be reached")
}

let optional = Int?.none
struct SomeError: Error {}

let y = try (optional ?? throw SomeError())

```

---

<div class="post-metadata">

**Author:** ![reitzig](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/reitzig/32/2054_2.png) [@reitzig](https://forums.swift.org/u/reitzig)\
**Post date:** [February 21, 2019, 12:22pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/15 "2019-02-21T12:22:00Z")

</div>

I think the friction (in my mind) comes from Swift having a rather colorful mix of built-in syntax and functions. Here, `throw` is a keyword (in a statement) but `??` is a function (that takes expressions) so they don't combine well. If they were both from the same category, natural solutions would exist.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [February 21, 2019, 4:18pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/16 "2019-02-21T16:18:12Z")

</div>

`throw` doesn't technically _need_ to be builtin syntax — there does have to be a primitive, but that could be hidden within a standard function the same way that it is in, say, SmallTalk — but that's quite common across languages. The limitation here is really just that it's a statement and not an expression. I think we'd be happy to consider a proposal to generalize it to be an expression; I can't guarantee that it'd be accepted, but I for one expect I'd support it.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 21, 2019, 4:31pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/17 "2019-02-21T16:31:07Z")

</div>

> [@John\_McCall](#):
>
> I don't think we'd want to make arbitrary uninhabited types act like bottom in the type system; that would almost certainly do nasty things to the type-checker.

Allowing specifically `Never` to act like bottom seems tractable, though, and is a direction we suggested going forward in our [resolution for rejecting the `!!` operator](https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/222). That combined with making `throw` into an expression sounds good to me.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [February 21, 2019, 4:44pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/18 "2019-02-21T16:44:38Z")

</div>

It's still quite problematic even if there's only one blessed bottom type. The issue is that it adds complexity to what you can do with unresolved type variables; normally if `τ < T` and `T` is concretely known to have no subtypes then you can deduce `τ = T`, but that's not true if you have a bottom type.

---

<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:** [February 21, 2019, 5:17pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/19 "2019-02-21T17:17:57Z")

</div>

> [@John\_McCall](#):
>
> It's still quite problematic even if there's only one blessed bottom type. The issue is that it adds complexity to what you can do with unresolved type variables; normally if `τ < T` and `T` is concretely known to have no subtypes then you can deduce `τ = T` , but that's not true if you have a bottom type.

Is there a way to treat it similarly to optional-promotion, whereby `Never` can be statically promoted to `T` as required?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 21, 2019, 5:20pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/20 "2019-02-21T17:20:12Z")

</div>

It's not obvious to me that it makes things any worse than they are now, since for an unresolved type variable there already isn't any guarantee that there are no subtypes, because of subclassing, existentials, `T < T?`, and so on.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [February 21, 2019, 5:33pm UTC](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722/21 "2019-02-21T17:33:13Z")

</div>

T was meant to be a concrete type head there. There are many concrete types that have no subtypes and for which we could otherwise immediately reach that conclusion.

[Next page](https://forums.swift.org/t/combining-with-throwing-when-theres-no-reasonable-default/20722.md?page=2)
