[Pitch] Introducing the "Unwrap or Die" operator to the standard library

"In -Ounchecked builds, the optimizer may assume that this function is never called. Failure to satisfy that assumption is a serious programming error.”

Yes, and so the following `!!` can perform identically to `!` in -Ounchecked builds when it is inlined.

Yes, I guess I wasn’t clear. I mean that there’s no problem.

···

On Jun 29, 2017, at 7:35 PM, Yuta Koshizawa <koher@koherent.org> wrote:

public static func !!(optional: Optional, errorMessage:
@autoclosure () -> String) -> Wrapped {
    precondition(optional != nil, errorMessage())
    return optional!
}

--
Yuta

2017-06-29 6:42 GMT+09:00 Jaden Geller <jaden.geller@gmail.com <mailto:jaden.geller@gmail.com>>:

> On Jun 28, 2017, at 7:47 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
>
>> On Jun 28, 2017, at 3:52 AM, Yuta Koshizawa via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> Hi, I think it is an orthogonal issue if we need a new operator. It is
>> also possible to introduce an infix `!` for it.
>>
>> I am sure that we do not need to avoid `precondition` as long as we
>> use it appropriately. It is useful to realize consistent behavior with
>> `Array`'s `subscript`, forced unwrapping `!`, `&+` and so on. In this
>> context, `precondition` does not mean a general word "precondition"
>> but the `precondition` function in the Swift standard library, which
>> is removed when -Ounchecked.
>
>
> How would the line run then? Would it simply act as a forced unwrapped under -Ounchecked?

From the docs:

"In -Ounchecked builds, the optimizer may assume that this function is never called. Failure to satisfy that assumption is a serious programming error.”

Aka, v. bad things happen if the precondition does not hold.

>
> -- E
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution

If/when Never is made a bottom time, I suppose this discussion will be moot because it will automatically work with ?? and the compiler would have to go out of its way to prevent that.

But until then, I much prefer guard-let-else to the proposed addition to ??. With a guard-let-else, the first word on the line tells you what’s going on, and when scanning through code you can quickly skim over that entire block as soon as you see “guard”. Guard-let-else makes it easy to understand the code at a glance. With the proposed addition to ??, you have to read all the way to the end of the line to understand that you’re exiting early with a fatal error. And in addition this lacks the flexibility of guard-let-else because you *must* fail; you cannot perform cleanup work and/or return gracefully.

While a convenient syntactic sugar, I foresee this addition making quickly understanding existing code much more difficult, and without much added convenience.

···

On Jun 30, 2017, at 5:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 30, 2017, at 5:38 AM, Matthew Johnson <matthew@anandabits.com> wrote:

3. If we later change `throw` from being a statement to being a `Never`-returning expression, you could use `throw` on the right-hand side of `??`.

What do you have in mind here? I don't recall any discussion of `throw` return Never. It seems like a novel use of a bottom type that might preclude the possibility of ever having a Result type that seamlessly bridges to Swift's error handling.

`throw` is currently a statement. Imagine, for sake of illustration, that it was instead a function. This function would take an `Error` as a parameter and throw it. It would never return normally—it would only return by throwing—so its return type would be `Never`:

  @_implicitlyTry
  func throw(_ error: Error) throws -> Never {
    try Builtin.throw(error)
    unreachable()
  }

What I'm suggesting is that `throw` should remain a keyword, but should have the semantics of this `throw(_:)` function. The parser should allow it in expression context, the `try` checker should treat it as though it was already marked `try`, and the type checker should treat it as an expression that returns `Never` but can throw.

That would then allow you to say things like:

  let lastItem = array.last ?? throw MyError.arrayEmpty

It would not have any negative effect I can think of on `Result`. In fact, trying to directly wrap a `throw SomeError.foo` statement in a `Result` would produce a `Result<Never, SomeError>`, correctly expressing the fact that the result of that particular expression can never be successful.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Even if ?? is generally assumed as safe, fatalError would be there to clearly assert what's going on. This is true in general for fatalError, which presence in some code simply means that something could go wrong there, so the regular compilation-level safety cannot be a given. And as forced unwrapping, fatalError - and other failures caused by a precondition - is not something that should be used lightly.

I think that "?? fatalError()" clearly conveys the meaning, is future-proof and could be adopted as a best practice.

Elviro

···

Il giorno 30 giu 2017, alle ore 17:39, Jacob Williams via swift-evolution <swift-evolution@swift.org> ha scritto:

I have been persuaded that extending the capabilities of the current ?? operator has far more advantages than adding a new limited !! operator. While I initially did not like the usage of the generally-assumed-safe ? for throwing operations, the clarity provided by having to explicitly state your ‘fatalError’ or ‘preconditionFailure’ etc, does make it obvious about what is going on.

Also, considering how this capability would eventually be possible with ?? anyways once Never become a true bottom type, it does not make sense to add a new operator that would essentially become deprecated in a short matter of time anyways. As many people have stated, the bar for additions to the Swift language should be, and is, exceptionally high. There just aren’t enough pro’s for the !! operator to make it worthwhile.

On Jun 30, 2017, at 9:31 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

These are all excellent points. I also feel they sidestep the motivation of the proposal. Even if there were a bottom `Never` and you could use `?? fatalError()`, I still think the language would benefit from `!!`.

As the language is right now, you can write your own "or die" function using a `guard` statement, overloading `??`, or implementing `!!`. Being able to duplicate an explanatory fail path isn't the point. Offering a best-practices alternative to `!!` that is easy to use, obvious to understand, and simple to adopt is.

As for the `#line` and `#file` issue, that is my biggest concern but I believe that can be surmounted.

-- E

On Jun 29, 2017, at 11:23 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Jun 27, 2017, at 10:16 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: bangbang.md · GitHub

Thank you for your thoughtful feedback, -- E

Finally found a few minutes to read this thread.

I'm a big fan of the `Never`-based approach. (I was before, but I am more so now.) Here are the points I can see in its favor:

1. It is extremely clear about what's happening—`!!` is another random operator to learn, but `fatalError(_:)` or `preconditionFailure(_:)` are fairly self-explanatory, and `??` is something you might already be using.

2. It allows you to control the optimization behavior by using `fatalError`, `preconditionFailure`, or `assertionFailure` as desired.

3. If we later change `throw` from being a statement to being a `Never`-returning expression, you could use `throw` on the right-hand side of `??`.

4. It supports other `Never`-returning operations, like `abort()` or `exit(_:)` or your custom `usage()` function, on the right side of `??`.

5. It supports file-and-line error reporting without having to add any new features; `!!` could not do this because an operator can't have extra, defaulted parameters to carry the file and line.

6. It harmonizes with the eventual idea of making `Never` a universal bottom type, but we don't actually have to implement that today, because we can just overload `??` for now.

Against these advantages, the only one I can see for `!!` is that it is terse. Terseness is good, especially for a feature which is competing with the single-character postfix `!` operator, but I can't help but be drawn to the flexibility and power of `??` with a `Never` expression on the right-hand side.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Personally, I strongly prefer `foo !! "explanation"` over `foo ?? fatalError()`. I don’t think adding another operator for what is a very common need is a concern, and is easier to read at a glance than the ??/fatalError combo. There is a bit of cognitive dissonance between ??, a normally-fluffy nonthreatening defaulting operator, and fatalError, a scary beware operator. `!!` OTOH matches `!` in clearly flagging the unwrap as unsafe and that your program will exit. I also think it would be easier to explain `!!` to beginners as part of a wider story explaining optionals in general, unwraps, what `nil` means and what `!` means etc. Whereas `foo ?? Never` requires a lot of heavy lifting to understand how/why it works – we might all understand it, but that understanding is built on a lot of foundational understanding.

I also think a `Never` type would be very useful. Just that for this particular case, `!!` is still worth adding too.

···

On Jun 28, 2017, at 6:03 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

In general, does everyone prefer `?? () -> Never` or `!! () -> Never`? I can argue both ways, with the goal in reading code as "unwrap or die".

The idea behind `?? () -> Never` is that it leaves no other choice in the
nil case but to do something that dies, and that something is typically a
function call like fatalError() that documents well enough the dying so !!
would be unnecessary. And since it was pointed out above that this can be
done today in the language with an autoclosure, I strongly believe that's
the direction we should go vs. defining a new operator.

In other words, !! doesn't fit with Never because it's not the *operator*
that's doing the dying, but the right-hand side of that operator.

···

On Wed, Jun 28, 2017 at 6:04 AM Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote:

I'll give this a kick around as soon as I get a moment and revise. I am
slightly concerned that we discussed variations of this in the past
(throwing if memory serves, with `Error` on the rhs) and that it broke the
expectations of nil-coalescing.

In general, does everyone prefer `?? () -> Never` or `!! () -> Never`? I
can argue both ways, with the goal in reading code as "unwrap or die".

-- E

On Jun 27, 2017, at 7:16 PM, Max Moiseev via swift-evolution < > swift-evolution@swift.org> wrote:

The compatibility testing revealed no related errors. And the full test
suite only shows one that I listed already.

Max

On Jun 27, 2017, at 3:28 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This solution is nifty indeed, and has the chief advantage of working.
On Tue, Jun 27, 2017 at 16:55 Max Moiseev via swift-evolution < > swift-evolution@swift.org> wrote:

On Jun 27, 2017, at 1:03 PM, Adrian Zubarev < >> adrian.zubarev@devandartist.com> wrote:

How about?

public func ?? <T>(optional: T?, noreturnOrError: @autoclosure () throws -> Never) rethrows -> T {
    switch optional {
    case .some(let value):
        return value
    case .none:
        try noreturnOrError()
    }
}

Yeah, I saw your email right after I sent mine =)
This works, I tried it and also ran the test suite. There was only one
error.

  var s: String = ns ?? "str" as String as String //
expected-error{{cannot convert value of type 'NSString?' to expected
argument type 'String?'}}

^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

cannot convert value of type 'String' to expected argument type 'NSString'

I now wonder what the effect on the source compatibility suite would be:
[NOT FOR MERGE][stdlib] Adding a variant of ??, with a Never returning closure by moiseev · Pull Request #10639 · apple/swift · GitHub

Max

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 21:54:57, Max Moiseev via swift-evolution (
swift-evolution@swift.org) schrieb:

On Jun 27, 2017, at 10:38 AM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

As you write, this operator becomes sugar for “?? fatalError()” once
Never becomes a true bottom type.

In the meantime, can’t the same thing be accomplished by overloading
fatalError so it’s a generic function that returns a discardable result of
type T, which in turn calls the Never-returning overload?

I like this idea more than adding an extra operator, but overloading
fatalError won’t work now because of
https://github.com/apple/swift/blob/master/stdlib/public/core/Optional.swift#L668

On Tue, Jun 27, 2017 at 12:25 Erica Sadun via swift-evolution < >> swift-evolution@swift.org> wrote:

Using an operator to provide feedback on the context of a failed unwrap
has become a commonly implemented approach in the Swift developer
Community. What are your thoughts about adopting this widely-used operator
into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here:
bangbang.md · GitHub

Thank you for your thoughtful feedback, -- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I'll give this a kick around as soon as I get a moment and revise. I am slightly concerned that we discussed variations of this in the past (throwing if memory serves, with `Error` on the rhs) and that it broke the expectations of nil-coalescing.

In general, does everyone prefer `?? () -> Never` or `!! () -> Never`? I can argue both ways, with the goal in reading code as "unwrap or die".

-- E

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

···

On 28 Jun 2017, at 15:03, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 27, 2017, at 7:16 PM, Max Moiseev via swift-evolution <swift-evolution@swift.org> wrote:

The compatibility testing revealed no related errors. And the full test suite only shows one that I listed already.

Max

On Jun 27, 2017, at 3:28 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This solution is nifty indeed, and has the chief advantage of working.
On Tue, Jun 27, 2017 at 16:55 Max Moiseev via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 27, 2017, at 1:03 PM, Adrian Zubarev <adrian.zubarev@devandartist.com> wrote:

How about?

public func ?? <T>(optional: T?, noreturnOrError: @autoclosure () throws -> Never) rethrows -> T {
    switch optional {
    case .some(let value):
        return value
    case .none:
        try noreturnOrError()
    }
}

Yeah, I saw your email right after I sent mine =)
This works, I tried it and also ran the test suite. There was only one error.

  var s: String = ns ?? "str" as String as String // expected-error{{cannot convert value of type 'NSString?' to expected argument type 'String?'}}
                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                     cannot convert value of type 'String' to expected argument type 'NSString'

I now wonder what the effect on the source compatibility suite would be:
[NOT FOR MERGE][stdlib] Adding a variant of ??, with a Never returning closure by moiseev · Pull Request #10639 · apple/swift · GitHub

Max

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 21:54:57, Max Moiseev via swift-evolution (swift-evolution@swift.org) schrieb:

On Jun 27, 2017, at 10:38 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

As you write, this operator becomes sugar for “?? fatalError()” once Never becomes a true bottom type.

In the meantime, can’t the same thing be accomplished by overloading fatalError so it’s a generic function that returns a discardable result of type T, which in turn calls the Never-returning overload?

I like this idea more than adding an extra operator, but overloading fatalError won’t work now because of https://github.com/apple/swift/blob/master/stdlib/public/core/Optional.swift#L668

On Tue, Jun 27, 2017 at 12:25 Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:
Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: bangbang.md · GitHub

Thank you for your thoughtful feedback, -- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

From that point of view, shouldn’t we then be talking about removing the postfix unary operator “!”? With this proposal it could just as easily be replaced with: ?? fatalError(“failed nil check”). But I don’t think anyone would take that suggestion seriously, so why are we not taking the idea of !! seriously either?

I really like the idea of having both:

let last = array.last ?? fatalError(“Reason”) // () → Never
let last = array.last !! “Reason”

The first one fits with the idea of Nil Coalescing and explicitly failing because of a precondition failure. Or as Tony put it, it “leaves no other choice … but to do something that dies”. It leaves open the case of having the error removed at certain -O levels.

The second one fits with the idea of logical failure where the operator itself is doing the dying, just like the unary version. And, like the force unwrap operator, it wouldn’t be removed at -Ounchecked.

Dave

···

On Jun 28, 2017, at 7:08 AM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

The idea behind `?? () -> Never` is that it leaves no other choice in the nil case but to do something that dies, and that something is typically a function call like fatalError() that documents well enough the dying so !! would be unnecessary. And since it was pointed out above that this can be done today in the language with an autoclosure, I strongly believe that's the direction we should go vs. defining a new operator.

In other words, !! doesn't fit with Never because it's not the *operator* that's doing the dying, but the right-hand side of that operator.

On Wed, Jun 28, 2017 at 6:04 AM Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I'll give this a kick around as soon as I get a moment and revise. I am slightly concerned that we discussed variations of this in the past (throwing if memory serves, with `Error` on the rhs) and that it broke the expectations of nil-coalescing.

In general, does everyone prefer `?? () -> Never` or `!! () -> Never`? I can argue both ways, with the goal in reading code as "unwrap or die".

-- E

On Jun 27, 2017, at 7:16 PM, Max Moiseev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The compatibility testing revealed no related errors. And the full test suite only shows one that I listed already.

Max

On Jun 27, 2017, at 3:28 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

This solution is nifty indeed, and has the chief advantage of working.
On Tue, Jun 27, 2017 at 16:55 Max Moiseev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 27, 2017, at 1:03 PM, Adrian Zubarev <adrian.zubarev@devandartist.com <mailto:adrian.zubarev@devandartist.com>> wrote:

How about?

public func ?? <T>(optional: T?, noreturnOrError: @autoclosure () throws -> Never) rethrows -> T {
    switch optional {
    case .some(let value):
        return value
    case .none:
        try noreturnOrError()
    }
}

Yeah, I saw your email right after I sent mine =)
This works, I tried it and also ran the test suite. There was only one error.

  var s: String = ns ?? "str" as String as String // expected-error{{cannot convert value of type 'NSString?' to expected argument type 'String?'}}
                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                     cannot convert value of type 'String' to expected argument type 'NSString'

I now wonder what the effect on the source compatibility suite would be:
[NOT FOR MERGE][stdlib] Adding a variant of ??, with a Never returning closure by moiseev · Pull Request #10639 · apple/swift · GitHub

Max

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 21:54:57, Max Moiseev via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

On Jun 27, 2017, at 10:38 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

As you write, this operator becomes sugar for “?? fatalError()” once Never becomes a true bottom type.

In the meantime, can’t the same thing be accomplished by overloading fatalError so it’s a generic function that returns a discardable result of type T, which in turn calls the Never-returning overload?

I like this idea more than adding an extra operator, but overloading fatalError won’t work now because of https://github.com/apple/swift/blob/master/stdlib/public/core/Optional.swift#L668

On Tue, Jun 27, 2017 at 12:25 Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: bangbang.md · GitHub

Thank you for your thoughtful feedback, -- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

···

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

I feel that the !! operator would be necessary for indicating that if this fails then something went horribly wrong somewhere and we should throw the fatalError. This allows the inclusion of optimizations using -Ounchecked and is clear that this is an operation that could result in a runtime error just like force unwrapping.

If we want code clarity and uniformity, then I think !! Is much better than ?? because it goes right along with the single ! Used for force unwrapping. However, this does depend on if the operator would be returning some kind of error that would cause the program to exit.

I think the ?? operator should not cause a program to exit early. It goes against optional unwrapping principles. I think code could get very confusing if some ? would return nil/a default value, and others would be causing your program to crash and exit. The ? operators should always be classified as safe operations.

···

On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

It's hard for me to articulate, but "foo !! message" feels a little too much like a Perl-ism for my taste. Objectively that's not a great criticism on its own, but I just don't like the "smell" of an operator that takes a value on one side and a string for error reporting purposes on the other. It doesn't feel like it fits the style of Swift. I prefer a version that makes the call to fatalError (and thus, any other non-returning handler) explicitly written out in code.

So, if the language can already support this with ?? and autoclosure/Never as was shown above, I'd rather see that added to the language instead of a new operator that does the same thing (and is actually less general).

I do see your point, and pardon my lack of familiarity with deeper swift capabilities, but would it be possible to restrict the !! operator to @noreturn closures rather than a string and just always throwing a fatalError? This would require the !! operator to have the error type explicitly spelt out, while still honoring the sentiment of !. It would feel more swifty, and you’d get the clarity of knowing that !! is an unsafe operation and you’d know exactly what kind of error is being thrown.

And then ?? could be left as-is and only used for default values.

···

On Jun 28, 2017, at 10:13 AM, Tony Allevato <tony.allevato@gmail.com> wrote:

On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I feel that the !! operator would be necessary for indicating that if this fails then something went horribly wrong somewhere and we should throw the fatalError. This allows the inclusion of optimizations using -Ounchecked and is clear that this is an operation that could result in a runtime error just like force unwrapping.

If we want code clarity and uniformity, then I think !! Is much better than ?? because it goes right along with the single ! Used for force unwrapping. However, this does depend on if the operator would be returning some kind of error that would cause the program to exit.

I think the ?? operator should not cause a program to exit early. It goes against optional unwrapping principles. I think code could get very confusing if some ? would return nil/a default value, and others would be causing your program to crash and exit. The ? operators should always be classified as safe operations.

On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

One argument against `?? () -> Never` is that `func f() -> Never { while true {} }` will also work.

Max

···

On Jun 28, 2017, at 8:35 AM, Ben Cohen <ben_cohen@apple.com> wrote:

On Jun 28, 2017, at 6:03 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

In general, does everyone prefer `?? () -> Never` or `!! () -> Never`? I can argue both ways, with the goal in reading code as "unwrap or die".

Personally, I strongly prefer `foo !! "explanation"` over `foo ?? fatalError()`. I don’t think adding another operator for what is a very common need is a concern, and is easier to read at a glance than the ??/fatalError combo. There is a bit of cognitive dissonance between ??, a normally-fluffy nonthreatening defaulting operator, and fatalError, a scary beware operator. `!!` OTOH matches `!` in clearly flagging the unwrap as unsafe and that your program will exit. I also think it would be easier to explain `!!` to beginners as part of a wider story explaining optionals in general, unwraps, what `nil` means and what `!` means etc. Whereas `foo ?? Never` requires a lot of heavy lifting to understand how/why it works – we might all understand it, but that understanding is built on a lot of foundational understanding.

I also think a `Never` type would be very useful. Just that for this particular case, `!!` is still worth adding too.

Instead of adding “@autoclosure ()->Never” to ??, why not make that the role of !! ? This would both make it clear that the unwrap is unsafe, like !, but also provide flexibility in how to report the error. E.G., optional !! fatalError(“oops”)

···

On Jun 28, 2017, at 11:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

It's hard for me to articulate, but "foo !! message" feels a little too
much like a Perl-ism for my taste. Objectively that's not a great criticism
on its own, but I just don't like the "smell" of an operator that takes a
value on one side and a string for error reporting purposes on the other.
It doesn't feel like it fits the style of Swift. I prefer a version that
makes the call to fatalError (and thus, any other non-returning handler)
explicitly written out in code.

So, if the language can already support this with ?? and autoclosure/Never
as was shown above, I'd rather see that added to the language instead of a
new operator that does the same thing (and is actually less general).

···

On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution < swift-evolution@swift.org> wrote:

I feel that the !! operator would be necessary for indicating that if this
fails then something went horribly wrong somewhere and we should throw the
fatalError. This allows the inclusion of optimizations using -Ounchecked
and is clear that this is an operation that could result in a runtime error
just like force unwrapping.

If we want code clarity and uniformity, then I think !! Is much better
than ?? because it goes right along with the single ! Used for force
unwrapping. However, this does depend on if the operator would be returning
some kind of error that would cause the program to exit.

I think the ?? operator should not cause a program to exit early. It goes
against optional unwrapping principles. I think code could get very
confusing if some ? would return nil/a default value, and others would be
causing your program to crash and exit. The ? operators should always be
classified as safe operations.

On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution < > swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution < > swift-evolution@swift.org> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to
burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into
existing patterns) is so burdensome seems way overweighted in this
discussion IMO.

Adding the operator, and encouraging its use, will help foster better
understanding of optionals and legitimate use of force-unwrapping in a way
that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

I have more difficulties saying the same for ?? as it provides a lot of value: a RHS Optional override and potentially a RHS Never closure override which would allow us to customise what happens before trapping. On the other hand, the !! operator, while useful, only provides a trapping behaviour with no way tu customise it.

···

On 28 Jun 2017, at 17:41, Ben Cohen <ben_cohen@apple.com> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

In general, does everyone prefer `?? () -> Never` or `!! () -> Never`? I can argue both ways, with the goal in reading code as "unwrap or die".

Personally, I strongly prefer `foo !! "explanation"` over `foo ?? fatalError()`. I don’t think adding another operator for what is a very common need is a concern, and is easier to read at a glance than the ??/fatalError combo. There is a bit of cognitive dissonance

Actually, the cognitive dissonance argument is a strong one. Its true that ?? doesn’t evoke trapping.

···

On 28 Jun 2017, at 17:35, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 6:03 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

between ??, a normally-fluffy nonthreatening defaulting operator, and fatalError, a scary beware operator. `!!` OTOH matches `!` in clearly flagging the unwrap as unsafe and that your program will exit. I also think it would be easier to explain `!!` to beginners as part of a wider story explaining optionals in general, unwraps, what `nil` means and what `!` means etc. Whereas `foo ?? Never` requires a lot of heavy lifting to understand how/why it works – we might all understand it, but that understanding is built on a lot of foundational understanding.

I also think a `Never` type would be very useful. Just that for this particular case, `!!` is still worth adding too.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Well the main debate is that, we all want early access to a feature that will be part of Swift as soon as `Never` becomes the bottom type. When this happens the `??` will automatically support the pitched behavior. Until then if we all agree that we should add it now in a way that will not break anything we can simply add an overload to `??` as I previously showed.

There is no need for `!!` because it will fade in the future. If you think of `Never` as a bottom type now then `??` will already make total sense. The default value for T from rhs might be T or Never.

@erica: the rhs argument should be called something like `noreturnOrError` and not `defaultValue`. And we should keep in mind that when Never becomes the bottom type we have to remove that overload from stdlib, because otherwise it will be ambiguous.

···

---

On the other hand if we tackle a different operator then we should rething the 'default value operator' because the second ? signals an optional but not a non-optional or an inplicit unwrapped operator. In that case I personally thing ?! would make more sense. Unwrap or (non-optional | IUO | trap/die)

--
Adrian Zubarev
Sent with Airmail

Am 28. Juni 2017 um 18:13:18, Tony Allevato via swift-evolution (swift-evolution@swift.org(mailto:swift-evolution@swift.org)) schrieb:

It's hard for me to articulate, but "foo !! message" feels a little too much like a Perl-ism for my taste. Objectively that's not a great criticism on its own, but I just don't like the "smell" of an operator that takes a value on one side and a string for error reporting purposes on the other. It doesn't feel like it fits the style of Swift. I prefer a version that makes the call to fatalError (and thus, any other non-returning handler) explicitly written out in code.

So, if the language can already support this with ?? and autoclosure/Never as was shown above, I'd rather see that added to the language instead of a new operator that does the same thing (and is actually less general).

On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution <swift-evolution@swift.org(mailto:swift-evolution@swift.org)> wrote:
> I feel that the !! operator would be necessary for indicating that if this fails then something went horribly wrong somewhere and we should throw the fatalError. This allows the inclusion of optimizations using -Ounchecked and is clear that this is an operation that could result in a runtime error just like force unwrapping.
>
> If we want code clarity and uniformity, then I think !! Is much better than ?? because it goes right along with the single ! Used for force unwrapping. However, this does depend on if the operator would be returning some kind of error that would cause the program to exit.
>
> I think the ?? operator should not cause a program to exit early. It goes against optional unwrapping principles. I think code could get very confusing if some ? would return nil/a default value, and others would be causing your program to crash and exit. The ? operators should always be classified as safe operations.
>
> > On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org(mailto:swift-evolution@swift.org)> wrote:
> >
> > > On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org(mailto:swift-evolution@swift.org)> wrote:
> > > Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.
> >
> > You could say the same about ??
> >
> > The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.
> >
> > Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Well the main debate is that, we all want early access to a feature that will be part of Swift as soon as `Never` becomes the bottom type. When this happens the `??` will automatically support the pitched behavior. Until then if we all agree that we should add it now in a way that will not break anything we can simply add an overload to `??` as I previously showed.

I believe we should add it now, but I like the recent observation that making ?? suddenly become a potentially crashing operator violates the expectation that ? is an indication of safety.

On the other hand, the existing semantics of Swift are that ! is always dangerous, so making !! be the a potentially crashing operator is much more consistent with the language.

There is no need for `!!` because it will fade in the future. If you think of `Never` as a bottom type now then `??` will already make total sense. The default value for T from rhs might be T or Never.

I respectfully disagree with your absolute position on this topic. Even with Never as a bottom type in the future, it would still be more convenient for me to type:

let last = array.last !! “Array must be non-empty"

… than it ever would be to type:

let last = array.last ?? fatalError(“Array must be non-empty”)

Dave

···

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

@erica: the rhs argument should be called something like `noreturnOrError` and not `defaultValue`. And we should keep in mind that when Never becomes the bottom type we have to remove that overload from stdlib, because otherwise it will be ambiguous.

---

On the other hand if we tackle a different operator then we should rething the 'default value operator' because the second ? signals an optional but not a non-optional or an inplicit unwrapped operator. In that case I personally thing ?! would make more sense. Unwrap or (non-optional | IUO | trap/die)

--
Adrian Zubarev
Sent with Airmail
Am 28. Juni 2017 um 18:13:18, Tony Allevato via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

It's hard for me to articulate, but "foo !! message" feels a little too much like a Perl-ism for my taste. Objectively that's not a great criticism on its own, but I just don't like the "smell" of an operator that takes a value on one side and a string for error reporting purposes on the other. It doesn't feel like it fits the style of Swift. I prefer a version that makes the call to fatalError (and thus, any other non-returning handler) explicitly written out in code.

So, if the language can already support this with ?? and autoclosure/Never as was shown above, I'd rather see that added to the language instead of a new operator that does the same thing (and is actually less general).

On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I feel that the !! operator would be necessary for indicating that if this fails then something went horribly wrong somewhere and we should throw the fatalError. This allows the inclusion of optimizations using -Ounchecked and is clear that this is an operation that could result in a runtime error just like force unwrapping.

If we want code clarity and uniformity, then I think !! Is much better than ?? because it goes right along with the single ! Used for force unwrapping. However, this does depend on if the operator would be returning some kind of error that would cause the program to exit.

I think the ?? operator should not cause a program to exit early. It goes against optional unwrapping principles. I think code could get very confusing if some ? would return nil/a default value, and others would be causing your program to crash and exit. The ? operators should always be classified as safe operations.

On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Based on the feedback on this thread, I'm coming to the following conclusions:

`!!` sends the right semantic message. "Unwrap or die" is an unsafe operation. It is based on `!`, the unsafe forced unwrap operator, and not on `??`, the safe fallback nil-coalescing operator. Its symbology should therefore follow `!` and not `?`.

The `!!` operator should follow the same semantics as `Optional.unsafelyUnwrapped`, which establishes a precedent for this approach:

"The unsafelyUnwrapped property provides the same value as the forced unwrap operator (postfix !). However, in optimized builds (-O), no check is performed to ensure that the current instance actually has a value. Accessing this property in the case of a nil value is a serious programming error and could lead to undefined behavior or a runtime error."

By following `Optional.unsafelyUnwrapped`, this approach is consistent with https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#logic-failures

"Logic failures are intended to be handled by fixing the code. It means checks of logic failures can be removed if the code is tested enough.

Actually checks of logic failures for various operations, `!`, `array[i]`, `&+` and so on, are designed and implemented to be removed
when we use `-Ounchecked`. It is useful for heavy computation like image processing and machine learning in which overhead of those checks is not permissible."

The right hand side should use a string (or more properly a string autoclosure) in preference to using a `Never` bottom type or a `() -> Never` closure. A string provides the cleanest user experience, and allows the greatest degree of self-documentation.

- A string is cleaner and more readable to type. It respects DRY, and avoids using *both* the operator and the call to `fatalError` or `preconditionFailure` to signal an unsafe condition:
`let last = array.last !! “Array guaranteed non-empty" // readable`
than:
`let last = array.last !! fatalError(“Array guaranteed non-empty”) // redundant, violates DRY`

- A string allows the operator *itself* to unsafely fail, just as the unary version of `!` does now. It does this with additional feedback to the developer during testing, code reading, and code maintenance. The string provides a self-auditing in-line annotation of the reason why the forced unwrap has been well considered, using a language construct to support this.

- A string disallows a potentially unsafe `Never` call that does not reflect a serious programming error, for example:
let last = array.last !! f() // where func f() -> Never { while true {} }

- Although as several list members mention, a `Never` closure solution is available today in Swift, so is the `!!` operator solution. Neither one requires a fundamental change to the language.

- Pushing forward on this proposal does not in any way reflect on adopting the still-desirable `Never` bottom type.

···

On Jun 28, 2017, at 12:42 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com <mailto:delong@apple.com>> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Well the main debate is that, we all want early access to a feature that will be part of Swift as soon as `Never` becomes the bottom type. When this happens the `??` will automatically support the pitched behavior. Until then if we all agree that we should add it now in a way that will not break anything we can simply add an overload to `??` as I previously showed.

I believe we should add it now, but I like the recent observation that making ?? suddenly become a potentially crashing operator violates the expectation that ? is an indication of safety.

?? does *not* become a potentially crashing operator. The *fatalError* (or whatever else the user chooses to put there) on the right-hand side is the crashing operation.

On the other hand, the existing semantics of Swift are that ! is always dangerous, so making !! be the a potentially crashing operator is much more consistent with the language.

There is no need for `!!` because it will fade in the future. If you think of `Never` as a bottom type now then `??` will already make total sense. The default value for T from rhs might be T or Never.

I respectfully disagree with your absolute position on this topic. Even with Never as a bottom type in the future, it would still be more convenient for me to type:

let last = array.last !! “Array must be non-empty"

… than it ever would be to type:

let last = array.last ?? fatalError(“Array must be non-empty”)

There is a very high bar for additions to the standard library—a new operator added to the language is going to be around (1) forever, or (2) indefinitely with some migration cost to users if it's ever removed. Shaving off a few keystrokes doesn't quite meet that bar—especially when an alternative has been shown to work already that provides the same functionality, is more general (not coupled to fatalError or String messages), and that fits better into Swift's design.

To make sure I'm not being too much of a downer, I would completely support this broader feature being implemented by that alternative: the ?? + autoclosure () -> Never combo. Then once Never does become a true bottom type, I believe it could be removed and the calling code would still *just work*.

Dave

@erica: the rhs argument should be called something like `noreturnOrError` and not `defaultValue`. And we should keep in mind that when Never becomes the bottom type we have to remove that overload from stdlib, because otherwise it will be ambiguous.

---

On the other hand if we tackle a different operator then we should rething the 'default value operator' because the second ? signals an optional but not a non-optional or an inplicit unwrapped operator. In that case I personally thing ?! would make more sense. Unwrap or (non-optional | IUO | trap/die)

--
Adrian Zubarev
Sent with Airmail
Am 28. Juni 2017 um 18:13:18, Tony Allevato via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

It's hard for me to articulate, but "foo !! message" feels a little too much like a Perl-ism for my taste. Objectively that's not a great criticism on its own, but I just don't like the "smell" of an operator that takes a value on one side and a string for error reporting purposes on the other. It doesn't feel like it fits the style of Swift. I prefer a version that makes the call to fatalError (and thus, any other non-returning handler) explicitly written out in code.

So, if the language can already support this with ?? and autoclosure/Never as was shown above, I'd rather see that added to the language instead of a new operator that does the same thing (and is actually less general).

On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I feel that the !! operator would be necessary for indicating that if this fails then something went horribly wrong somewhere and we should throw the fatalError. This allows the inclusion of optimizations using -Ounchecked and is clear that this is an operation that could result in a runtime error just like force unwrapping.

If we want code clarity and uniformity, then I think !! Is much better than ?? because it goes right along with the single ! Used for force unwrapping. However, this does depend on if the operator would be returning some kind of error that would cause the program to exit.

I think the ?? operator should not cause a program to exit early. It goes against optional unwrapping principles. I think code could get very confusing if some ? would return nil/a default value, and others would be causing your program to crash and exit. The ? operators should always be classified as safe operations.

On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m strongly against not using the `??` operator for `x ?? fatalError()` since that is naturally what will be possible once the `Never` type is a real bottom type. If you want to use `!!` for the `x !! “bad things!”` convenience form, I don’t care. But the `Never` form should definitely, definitely use `??`.

···

On Jun 28, 2017, at 1:30 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Based on the feedback on this thread, I'm coming to the following conclusions:

`!!` sends the right semantic message. "Unwrap or die" is an unsafe operation. It is based on `!`, the unsafe forced unwrap operator, and not on `??`, the safe fallback nil-coalescing operator. Its symbology should therefore follow `!` and not `?`.

The `!!` operator should follow the same semantics as `Optional.unsafelyUnwrapped`, which establishes a precedent for this approach:

> "The unsafelyUnwrapped property provides the same value as the forced unwrap operator (postfix !). However, in optimized builds (-O), no check is performed to ensure that the current instance actually has a value. Accessing this property in the case of a nil value is a serious programming error and could lead to undefined behavior or a runtime error."

By following `Optional.unsafelyUnwrapped`, this approach is consistent with https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#logic-failures

> "Logic failures are intended to be handled by fixing the code. It means checks of logic failures can be removed if the code is tested enough.
Actually checks of logic failures for various operations, `!`, `array[i]`, `&+` and so on, are designed and implemented to be removed
when we use `-Ounchecked`. It is useful for heavy computation like image processing and machine learning in which overhead of those checks is not permissible."

The right hand side should use a string (or more properly a string autoclosure) in preference to using a `Never` bottom type or a `() -> Never` closure. A string provides the cleanest user experience, and allows the greatest degree of self-documentation.

- A string is cleaner and more readable to type. It respects DRY, and avoids using *both* the operator and the call to `fatalError` or `preconditionFailure` to signal an unsafe condition:
`let last = array.last !! “Array guaranteed non-empty" // readable`
than:
`let last = array.last !! fatalError(“Array guaranteed non-empty”) // redundant, violates DRY`

- A string allows the operator *itself* to unsafely fail, just as the unary version of `!` does now. It does this with additional feedback to the developer during testing, code reading, and code maintenance. The string provides a self-auditing in-line annotation of the reason why the forced unwrap has been well considered, using a language construct to support this.

- A string disallows a potentially unsafe `Never` call that does not reflect a serious programming error, for example:
let last = array.last !! f() // where func f() -> Never { while true {} }

- Although as several list members mention, a `Never` closure solution is available today in Swift, so is the `!!` operator solution. Neither one requires a fundamental change to the language.

- Pushing forward on this proposal does not in any way reflect on adopting the still-desirable `Never` bottom type.

On Jun 28, 2017, at 12:42 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com <mailto:delong@apple.com>> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Well the main debate is that, we all want early access to a feature that will be part of Swift as soon as `Never` becomes the bottom type. When this happens the `??` will automatically support the pitched behavior. Until then if we all agree that we should add it now in a way that will not break anything we can simply add an overload to `??` as I previously showed.

I believe we should add it now, but I like the recent observation that making ?? suddenly become a potentially crashing operator violates the expectation that ? is an indication of safety.

?? does *not* become a potentially crashing operator. The *fatalError* (or whatever else the user chooses to put there) on the right-hand side is the crashing operation.

On the other hand, the existing semantics of Swift are that ! is always dangerous, so making !! be the a potentially crashing operator is much more consistent with the language.

There is no need for `!!` because it will fade in the future. If you think of `Never` as a bottom type now then `??` will already make total sense. The default value for T from rhs might be T or Never.

I respectfully disagree with your absolute position on this topic. Even with Never as a bottom type in the future, it would still be more convenient for me to type:

let last = array.last !! “Array must be non-empty"

… than it ever would be to type:

let last = array.last ?? fatalError(“Array must be non-empty”)

There is a very high bar for additions to the standard library—a new operator added to the language is going to be around (1) forever, or (2) indefinitely with some migration cost to users if it's ever removed. Shaving off a few keystrokes doesn't quite meet that bar—especially when an alternative has been shown to work already that provides the same functionality, is more general (not coupled to fatalError or String messages), and that fits better into Swift's design.

To make sure I'm not being too much of a downer, I would completely support this broader feature being implemented by that alternative: the ?? + autoclosure () -> Never combo. Then once Never does become a true bottom type, I believe it could be removed and the calling code would still *just work*.

Dave

@erica: the rhs argument should be called something like `noreturnOrError` and not `defaultValue`. And we should keep in mind that when Never becomes the bottom type we have to remove that overload from stdlib, because otherwise it will be ambiguous.

---

On the other hand if we tackle a different operator then we should rething the 'default value operator' because the second ? signals an optional but not a non-optional or an inplicit unwrapped operator. In that case I personally thing ?! would make more sense. Unwrap or (non-optional | IUO | trap/die)

--
Adrian Zubarev
Sent with Airmail
Am 28. Juni 2017 um 18:13:18, Tony Allevato via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

It's hard for me to articulate, but "foo !! message" feels a little too much like a Perl-ism for my taste. Objectively that's not a great criticism on its own, but I just don't like the "smell" of an operator that takes a value on one side and a string for error reporting purposes on the other. It doesn't feel like it fits the style of Swift. I prefer a version that makes the call to fatalError (and thus, any other non-returning handler) explicitly written out in code.

So, if the language can already support this with ?? and autoclosure/Never as was shown above, I'd rather see that added to the language instead of a new operator that does the same thing (and is actually less general).

On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I feel that the !! operator would be necessary for indicating that if this fails then something went horribly wrong somewhere and we should throw the fatalError. This allows the inclusion of optimizations using -Ounchecked and is clear that this is an operation that could result in a runtime error just like force unwrapping.

If we want code clarity and uniformity, then I think !! Is much better than ?? because it goes right along with the single ! Used for force unwrapping. However, this does depend on if the operator would be returning some kind of error that would cause the program to exit.

I think the ?? operator should not cause a program to exit early. It goes against optional unwrapping principles. I think code could get very confusing if some ? would return nil/a default value, and others would be causing your program to crash and exit. The ? operators should always be classified as safe operations.

On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Count me in as a strong proponent of ?? () -> Never. We don't need to burden the language with an extra operator just for that.

You could say the same about ??

The concern that an additional operator (and one that, IMO, fits well into existing patterns) is so burdensome seems way overweighted in this discussion IMO.

Adding the operator, and encouraging its use, will help foster better understanding of optionals and legitimate use of force-unwrapping in a way that I don’t think `?? fatalError` could.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Note that 'unsafelyUnwrapped' does not perform the check in optimized builds (like 'assert'), while '!' does (like 'precondition'). If we go with '!!', it should behave like 'precondition', not 'assert'.

Jordan

···

On Jun 28, 2017, at 14:40, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

The `!!` operator should follow the same semantics as `Optional.unsafelyUnwrapped`, which establishes a precedent for this approach:

> "The unsafelyUnwrapped property provides the same value as the forced unwrap operator (postfix !). However, in optimized builds (-O), no check is performed to ensure that the current instance actually has a value. Accessing this property in the case of a nil value is a serious programming error and could lead to undefined behavior or a runtime error."