[SR-7486] assertionFailure should be deprecated or removed. #50029
Labels
bug
A deviation from expected or documented behavior. Also: expected but undesirable behavior.
standard library
Area: Standard library umbrella
Environment
Swift 4.1
Additional Detail from JIRA
md5: af2934e947ca5938fcdef4fe1e558ae1
Issue Description:
While investigating whether it was possible to convince Swift that a branch is unreachable, I discovered that
assertionFailure
is extremely surprising, and seems to have no sensible use-cases.Consider the following simple function:
When attempting to compile this function in debug mode, the following compiler error is emitted:
This is naturally fairly perplexing, but if the code is changed to add a return value, we could end up with the following program:
When compiled in debug mode and run, this produces the following output, as expected:
When compiled with optimisations and run, this produces the following output:
This strange strange behaviour boils down to the fact that `assertionFailure` is compiled away entirely in release mode. This means that it cannot be defined as returning `Never`, which is why surprise number 1 happens (namely, that you are forced to exit the `guard` scope in debug mode). And because it's compiled away in release mode, you run straight through it in release mode.
This function basically seems to be a worse-in-every-way version of `preconditionFailure`. It seems to serve no purpose. The distinction between
assert
andprecondition
is reasonable, as it allows coders to elide expensive checks that do not need to be run in release mode, but that does not apply here:assertionFailure
andpreconditionFailure
are not expensive.This confusion is widespread. For example, here is a blog post (Swift assertions: the missing manual) that mistakenly claims:
"Main difference is that assertionFailure() gives a hint to the optimizer that at this point, given context ("if" branch, or function context) ends, making it the @NoReturn effectively. In debug mode application will terminate, but in release behaviour is undefined."
This is not an accurate description of the behaviour of the function. I'd argue that it actually describes a more useful version of the function, where
assertionFailure
could be used to inform the compiler that a given branch should be unreachable. This was the effect I was trying to achieve when I bumped into this behaviour.The text was updated successfully, but these errors were encountered: