On Monday, 21 May 2018 at 19:44:17 UTC, Jonathan M Davis wrote:
Walter wants to use assertions to then have the compiler make
assumptions about the code and optimized based on it, but he
hasn't implemented anything like that, and there are a number
of arguments about why it's a very bad idea - in particular, if
it allows the compiler to have undefined behavior if the
assertion would have failed if it were left in. So, what is
actually going to happen with that is unclear. There are folks
who want additional performance benefits by allowing assertions
to work as hints to the compiler, and there are folks who want
them to truly just be for debugging purposes, because they
don't want the compiler to then generate code that makes the
function behave even more badly when the assertion would have
failed but had been compiled out.
If your code is based on untrue assumptions, you probably have a
bug anyways. If you used asserts and an optimization brought it
in, you will at least find it as soon as you remove the release
flag.
It shouldn't be a problem to make it a compiler flag for those
who don't want it. Defaulted to true with -O3 but can be turned
off with -fno-assert-optimize or something like that.
Personally, my big concern is that it can't introduce undefined
behavior, or it would potentially violate memory safety in
@safe code, which would then mean that using assertions in
@safe code could make your code effectively @system, which
would defeat the whole purpose of @safe.
Fair point, that probably limits the optimiations that can be
done. If I have an assert that an array has 10 elements when it
actually has only 3 and do some operations on it, that could
read/write to memory I have never allocated.
However some optimations should still be possible in SafeD, like
ignoring if conditions where the results are known at compile
time if the asserts are true.
Or loop unrolling and auto-vectorization without checking for the
rest should also be possible if you have an assert, that the
length of an array is divisible by something.
Neither of them should be able to add unsafe instructions. The
worst that could happen is relying on a wrong value to access an
element of an array and fail a bounds check.
assertNotThrown doesn't use any assertions. It explicitly
throws an AssertError (which is what a failed assertion does
when it's not compiled out). assertNotThrown would have to use
a version(assert) block to version the checks to try and mirror
what the assert statement does. However, assertNotThrown is
specifically intended for unit tests. IIRC, assertions in unit
tests are left in when compiled with -unittest (otherwise,
compiling with -release and -unittest - like Phobos does for
one of its passes as part of its unittest build - would not
work), but I don't think that the assertions outside of
unittest blocks get left in in that case, so using
version(assert) on assertThrown or assertNotThrown might break
them. I'm not sure. Regardless, using them for testing what
assertions do is just wrong. You need to test actual assert
statements if that's what you want to be testing.
Okay, clearly a misunderstanding on my side then. Thanks for
clarifying that.