On Sunday, 2 September 2018 at 02:32:31 UTC, Jonathan M Davis
wrote:
On Saturday, September 1, 2018 2:15:15 PM MDT Walter Bright via
Digitalmars- d wrote:
https://blog.regehr.org/archives/1091
As usual, John nails it in a particularly well-written essay.
"ASSERT(expr)
Asserts that an expression is true. The expression may or may
not be
evaluated. If the expression is true, execution continues
normally.
If the expression is false, what happens is undefined."
Note the "may or may not be evaluated." We've debated this
here before. I'm rather pleased that John agrees with me on
this. I.e. the optimizer can assume the expression is true and
use that information to generate better code, even if the
assert code generation is turned off.
Personally, my concern about letting the compiler optimize
based on assertions has to do with whether it violates @safe.
IMHO, it defeats the purpose of @safe if adding an assertion
can result in @system code due to optimizations. I'm fine with
it optimizing so long as the optimizations will not result in
@safe code becoming @system in the case where the assertion
would have failed if it were compiled in. If @safe allows
@system optimizations than it isn't actually @safe, because
while we don't want assertions to ever turn out to be false,
they sometimes do turn out to be false, and if they're not
compiled in, it's not going to be caught. That then is
obviously a bug, but at least it isn't one that's going to
corrupt memory (at least if it's in @safe code), but if the
compiler is allowed to optimize based on the assertion to the
point that the code could corrupt memory if the assertion would
have failed, then that's a serious problem and a total
violation of the promises made by @safe. And actually, it can't
add @system optimizations even in @system code, because that
completely defeats the ability of the programmer to verify the
code for @safety in order to use @trusted.
If the compiler can add @safe optimizations based on
assertions, then that's fine with me (though I know that some
others don't agree), but they have to be @safe even when the
assertion would have failed if it were compiled in. If they're
ever @system, then @safe isn't actually @safe.
- Jonathan M Davis
I believe asserts are the general case of which bounds checking
is a specific instance. @safe code is only @safe if
bounds-checking is enabled for @safe.
void foo(int[] a) @safe
{
a[0] = 1;
}
is only really guaranteed safe if a bounds check is done, because
[] is a valid array for a caller to pass.
void foo(int[] a) @safe
{
assert(a.length == 1);
a[0] = 1;
}
if asserts can be used as guarantees for the optimiser even when
removed, this code is only @safe when asserts are enabled
(because otherwise the bounds checks would be elided as they are
guaranteed to pass).
So, essentially we just have to treat asserts like bounds checks
and @safe will work as expected.
P.S.
// assert
debug assert(cond, msg);
// assume
assert(cond, msg);