Resolved: Insert "!" is a bad fixit

I’m not a fan of the “unwrap or die” operator in isolation, but it doesn’t offend me to the extent of trying to prevent it entering the language. However, I find the motivation in the proposal troubling, and would like to explore the logic of that a bit.

The point about “die” is that we only want to do that in the case of what we call “programmer error”. Let’s start looking at cases:


(#1) We unwrap an optional that “cannot” be nil.

For example, the unwrap may be in a line immediately following a test for nil that leaves the scope if the optional’s value is nil. Since the error “can never happen”, there is no point in using !! instead of !.


(#2) But of course, programmers can make errors…

…so there are cases where we would actually "die" if there were a programmer error. The proposed solution seeks to “improve” this by providing an error message that “explains” what went wrong. That’s better than just crashing, isn’t it?

Well, no. If you can explain what went wrong, that means you know what the error was. If you know what the error was, the correct procedure is to go correct the error, not to code an error message and leave the error fatally lurking in the code.

An example of this scenario might be when you have a URL string that you want to turn into a URL object, and this string has already been validated as correctly-formed. If you can’t form a URL from the string, then something has gone horribly and inexplicably wrong somewhere.

But there’s really no point in using “unwrap or die” with a message like “A valid URL string failed to initialize a URL”, because you can generally craft a solution to the problem that doesn’t involve dying. For example, if URL initialization fails, it may be proper to treat the valid URL string as an invalid string, which is a class of non-fatal errors that already has an existing escape hatch (say via throw). Or you can invent a new escape hatch.


(#3) Actually, I went a bit too far in that previous paragraph. An escape hatch may not be feasible in practice.

Now you have an optional that’s nil, and it shouldn’t be, and you have no idea why, and you have no practical recovery mechanism. In this case, “die” is actually the only solution, but now the "unwrap or die" operator has a problem with the error message.

The message can’t explain anything (because you don’t know the explanation — if you did, this problem would eliminable under #2 above). What you’re left with is to use what is basically an arbitrary, unique string. All it's good for is to locate the source line if the string ever shows up in a console log just before a crash.


That’s the trouble I have with the motivation for the “unwrap or die” operator. It purports to explain an error, but it's only useful in a situation where no real explanation is available.

I have, of course, overstated my case in order to keep this post from being longer than it is. Things are never that simple, and the “unwrap or die” operator might be something we want in the Swift language anyway. But as a mitigation of the “bad” fixit problem, I don’t think it’s a strongly appealing candidate.

(Also, apologies for all the "air quotes". Stylistically bad, I know.)

5 Likes