assertNotThrown (and asserts in general)

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon May 21 19:44:17 UTC 2018


On Monday, May 21, 2018 12:44:21 Malte via Digitalmars-d-learn wrote:
> I was interested by asserts and how the compiler uses them to
> optimize the code. So I looked at the compiler explorer to see
> how and found it, it doesn't.
>
> What I tried to do is turn a std.conv.to!ulong(byte) to a simple
> cast with the help of assertions.
> https://godbolt.org/g/4uckWU
>
> If there is an assert right before an if with the same condition,
> I think it should remove the compare and jump in release, but it
> doesn't. I'm assuming the compilers just aren't ready yet, but
> should be someday. At least that is what the documentation
> promises.

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.

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. If the compiler can
optimize while not breaking those guarantees, then I'm all for it, but some
folks disagree with even that, because they don't want their code to behave
worse when something goes wrong. Of course, the counter-argument is that if
they're that worried about it, they should leave the checks in, but there
definitely isn't agreement on the matter. Walter is in favor of adding
optimizations based on assertions though, so I think that there's a decent
chance that we'll see something like that at some point. But language
feature stuff (like implementing scope for DIP 1000) are generally much
higher priority than adding extra optimizations to the compiler. So, while
optimizations and performance improvements are certainly done, they're not
the main focus right now.

> More curious made me
> "assertNotThrown!ConvOverflowException(input.to!ubyte)" where it
> didn't even remove the assert code in release and produced the
> most inefficient assembly.
> Is that intended behaviour? In my opinion that greatly limits the
> usabilty of it.

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.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list