I think we're lacking a good option for assert failure behaviour for released code. Basically, we have two options.
One, crashing on assert failure. This may be a performance problem. It is customary for D code to assume the assertions will be removed on released code, and thus they are often used with little regard for performance.
Two, undefined behaviour. Of course, if an assert has gone boom it's not good news no matter what we do. The problem with undefined behaviour is that it defeats the purpose of leaving bounds checks in released code:
@safe pure int fun(int[] arg)
{ import std.algorithm, std.range;
assert(arg.length >= 10);
// Cannot go out of bounds without violating the assertion above.
// Array bounds check may be skipped.
return arg.takeExactly(10).sum;
}
IMO we need an option for the compiler to delete the assertions, without being allowed to assume the assertion holds. The compiler would still be free to crash on assertion failure, if it deems that better for performance, but it could not trigger undefined behaviour. In other words, the compiler would treat assert(x)
the same as:
if(!x)
{ int v = void;
if(v > 0) assert(false);
}
I also think this option should be the default, unless -boundscheck=off
.