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);

Reply via email to