What is the reason for precondition(condition:message:) to fail silently in release builds?

I literally spent 7+ hours debugging crashing web server with 132 exit code. At first I thought it's a swift-docker related problem, but then I found out in stdlib source code (and shortly after that in official documentation, lol) that precondition shows error message only in debug builds, otherwise just trap.

I can't come up with any reason to do that, because obviously a) this is what precondition is made for — to do sanity checks not just in debug builds (like assert), but also in release and b) it makes it ten times harder to debug crashing production build.

Preconditions are disabled in -Ounchecked builds; do you happen to be building in that mode? guard else fatalError() is the only option for -Ounchecked as far as I know.



The condition to test. condition is not evaluated in -Ounchecked builds.

Edit: sorry, I didn’t read the post/documentation properly.

Well, I believe release build isn't -0unchecked, so condition() is still evaluated, but fail is silent, and this is where I get frustrated. And, well, yeah, already have my own precondition with fatalError and stuff...

If it kept the message, what would be the difference between it and fatalError?

The way I understand it, precondition is intended as a compromise between assert and fatalError, where the compiler is allowed to optimize away everything related to constructing the message, but it won’t optimize away the check itself, so that the program is safe from spiraling into undefined territory.

For some examples of why someone would want to have the message stripped, see this thread:

This is a known, long standing issue: https://bugs.swift.org/browse/SR-905

Should be fixed by https://github.com/apple/swift/pull/25978

It would be absolute awesomeness! However, shouldn't've it gone through evolution process?

Diagnostics improvements don’t need review through Swift Evolution.

Especially those filed under "bugs"

The documentation comment still implies the message is dropped. (Compare with the comment for assert.)

I kind of miss the old behaviour. This new behaviour was possible to construct on top of the old by directing through fatalError, but I don’t know how to reconstruct the old on top of the new.

Terms of Service

Privacy Policy

Cookie Policy