John Regehr on "Use of Assertions"

2018-09-01 Thread Walter Bright via Digitalmars-d

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.


Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Guillaume Boucher via Digitalmars-d
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright 
wrote:
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.


You only read what you want to hear or what?

His essay is built up in a way where he shows two opposing 
interpretations of
asserts.  Assertions as "bug detectors" or as "optimizer hints".  
He then
discusses which one of those is the better one.  The quote you 
gave is the
definition from a proponent of the "optimizer hint" camp and not 
necessarily what

John agrees with.

His conclusion in the essay is that in general it makes sense to 
have assertions
enabled even in release builds because a slightly worse 
performance is worth it
to have more robust programs and he has backed this up by a lot 
of examples.


Furthermore, he wrote a follow-up post about "assume"
(https://blog.regehr.org/archives/1096).  Assume seems to be what 
you think

assert is, but there is actually a *huge* difference.

We assert a condition when we believe it to be true in every 
non-buggy
execution of our program, but we want to be notified if this 
isn’t the case. In
contrast, we assume a condition when our belief in its truth is 
so strong that
we don’t care what happens if it is ever false. In other words, 
while
assertions are fundamentally pessimistic, assumptions are 
optimistic.


So no, John doesn't agree with you on this *at all*.



Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Walter Bright via Digitalmars-d

On 9/1/2018 3:23 PM, Guillaume Boucher wrote:

On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:
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.


You only read what you want to hear or what?

His essay is built up in a way where he shows two opposing interpretations of
asserts.  Assertions as "bug detectors" or as "optimizer hints". He then
discusses which one of those is the better one.  The quote you gave is the
definition from a proponent of the "optimizer hint" camp and not necessarily 
what
John agrees with.

His conclusion in the essay is that in general it makes sense to have assertions
enabled even in release builds because a slightly worse performance is worth it
to have more robust programs and he has backed this up by a lot of examples.


He says:

"Therefore, the compiler should feel free to optimize the program under the 
assumption that the asserted condition holds. Although this might be what we 
want — in fact it would be really cool if adding assertions made our code faster 
rather than slower — it’s not an interpretation that is universally useful. As 
developers, we might want to count on a certain kind of behavior when an 
assertion fails."


"not ... universally useful" is not quite not agreeing at all.



Furthermore, he wrote a follow-up post about "assume"
(https://blog.regehr.org/archives/1096).  Assume seems to be what you think
assert is, but there is actually a *huge* difference.


We assert a condition when we believe it to be true in every non-buggy
execution of our program, but we want to be notified if this isn’t the case. In
contrast, we assume a condition when our belief in its truth is so strong that
we don’t care what happens if it is ever false. In other words, while
assertions are fundamentally pessimistic, assumptions are optimistic.


So no, John doesn't agree with you on this *at all*.


I don't interpret it that way. Disabling runtime assert checking turns them into 
assumes. John is implying asserts should never be disabled.




Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 09/01/2018 07:54 PM, Walter Bright wrote:

On 9/1/2018 3:23 PM, Guillaume Boucher wrote:

On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:


[John agrees with me.]


[No, he doesn't.]


[Yea-huh, he does.]



You're both wrong. ;) Or actually, you're both right...

There's a section with the following heading:

   "Are Assertions Enabled in Production Code?"

First sentence of that section:

   "This is entirely situational."

One point for "John agrees with Walter."

HOWEVER, Walter has also expressed that a program should never continue 
after an assert failure. The concluding text of the same section:


   "[...rather interesting counterexample from NASA/Mars...] The 
question of whether it is better to stop or keep going when an internal 
bug is detected is not a straightforward one to answer."


One point for "John disagrees with Walter."


Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 09/01/2018 08:44 PM, Nick Sabalausky (Abscissa) wrote:


    "Are Assertions Enabled in Production Code?"
    "This is entirely situational."
    "The question of whether it is better to stop or keep going when an internal 
bug is detected is not a straightforward one to answer."



All in all, John is very non-committal about the whole thing.


Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 09/01/2018 08:44 PM, Nick Sabalausky (Abscissa) wrote:


You're both wrong. ;) Or actually, you're both right...



That said, it IS a very interesting, well-written article.


Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Walter Bright via Digitalmars-d

On 9/1/2018 5:47 PM, Nick Sabalausky (Abscissa) wrote:

All in all, John is very non-committal about the whole thing.


He probably got tired of arguing about it :-)


Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Jonathan M Davis via Digitalmars-d
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





Re: John Regehr on "Use of Assertions"

2018-09-02 Thread Trass3r via Digitalmars-d
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright 
wrote:
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.


It shouldn't allow side-effects then though.
https://run.dlang.io/is/P6VnYd

Also a common source of bugs in C.


Re: John Regehr on "Use of Assertions"

2018-09-02 Thread John Colvin via Digitalmars-d
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);


Re: John Regehr on "Use of Assertions"

2018-09-02 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 09/01/2018 04:15 PM, Walter Bright wrote:

https://blog.regehr.org/archives/1091



This does make me think of one thing: Shouldn't assert expressions be 
required to be pure? (even if only weakly pure)


Not sure how much practical problems that would create, but at least in 
theory it certainly sounds like the right thing.


Re: John Regehr on "Use of Assertions"

2018-09-02 Thread Jonathan M Davis via Digitalmars-d
On Sunday, September 2, 2018 1:52:34 PM MDT John Colvin via Digitalmars-d 
wrote:
> > 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.
>
> 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.

Well, if that were the intention, then -release could not remove assertions
from @safe code. -release does not remove bounds checking from @safe code.
You have to use -boundscheck=off to disable assertions in @safe code (which
is of course discouraged, since it makes the code not @safe). So, if we were
to decide that assertions had to be left in for code to stay @safe, then we
would have to start leaving them in in @safe code when -release is used and
only compile them out with a new flag specifically for compiling out
assertions in @safe code. And that would have pretty far-reaching effects
given that it's very much understood right now that -release removes
assertions. And personally, I'd probably use assertions a lot less if they
were going to be left in with -release. So, while I think that that's a
better approach that allowing @system optimizations in @safe code when
assertions are removed, I can't say that I think that it's a great idea -
though the folks who pretty much always want assertions enabled would
probably like it (though they can already just skip -release).

- Jonathan M Davis





Re: John Regehr on "Use of Assertions"

2018-09-03 Thread John Colvin via Digitalmars-d
On Monday, 3 September 2018 at 06:26:59 UTC, Jonathan M Davis 
wrote:
Well, if that were the intention, then -release could not 
remove assertions from @safe code. -release does not remove 
bounds checking from @safe code. You have to use 
-boundscheck=off to disable assertions in @safe code (which is 
of course discouraged, since it makes the code not @safe). So, 
if we were to decide that assertions had to be left in for code 
to stay @safe, then we would have to start leaving them in in 
@safe code when -release is used and only compile them out with 
a new flag specifically for compiling out assertions in @safe 
code. And that would have pretty far-reaching effects given 
that it's very much understood right now that -release removes 
assertions. And personally, I'd probably use assertions a lot 
less if they were going to be left in with -release. So, while 
I think that that's a better approach that allowing @system 
optimizations in @safe code when assertions are removed, I 
can't say that I think that it's a great idea - though the 
folks who pretty much always want assertions enabled would 
probably like it (though they can already just skip -release).


- Jonathan M Davis


Yes, the command line interface needs to make it easy and obvious 
to do the right thing.


Re: John Regehr on "Use of Assertions"

2018-09-03 Thread Meta via Digitalmars-d
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright 
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.


I used to completely agree with your position about asserts being 
used for optimization purposes, until I realized that part of 
your position was for asserts to be used as optimization hints 
*even if they aren't checked*.


This battle has been fought over and over, with no movement on 
either side, so I'll just comment that nobody what John Nails or 
anyone else says, my personal opinion is that you're 100% wrong 
on that point :-)


Re: John Regehr on "Use of Assertions"

2018-09-03 Thread Trass3r via Digitalmars-d
On Sunday, 2 September 2018 at 21:12:39 UTC, Nick Sabalausky 
(Abscissa) wrote:
This does make me think of one thing: Shouldn't assert 
expressions be required to be pure? (even if only weakly pure)


Not sure how much practical problems that would create, but at 
least in theory it certainly sounds like the right thing.


Exactly. You may still catch assert(!fclose(f)) but not other 
non-obvious functions.

Nice trick to find them in C:
https://stackoverflow.com/questions/10593492/catching-assert-with-side-effects/35294344#35294344


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Walter Bright via Digitalmars-d

On 9/2/2018 2:12 PM, Nick Sabalausky (Abscissa) wrote:

On 09/01/2018 04:15 PM, Walter Bright wrote:

https://blog.regehr.org/archives/1091



This does make me think of one thing: Shouldn't assert expressions be required 
to be pure? (even if only weakly pure)


Not sure how much practical problems that would create, but at least in theory 
it certainly sounds like the right thing.


It's come up before. The trouble comes when the code doing the evaluation has 
side effects which are benign to the function being compiled, and these can be 
useful. For example, it could read a mutable global variable.


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Ola Fosheim Grøstad via Digitalmars-d

On Monday, 3 September 2018 at 16:53:35 UTC, Meta wrote:
This battle has been fought over and over, with no movement on 
either side, so I'll just comment that nobody what John Nails 
or anyone else says, my personal opinion is that you're 100% 
wrong on that point :-)


Well, John Regehr seems to argue that you shouldn't use asserts 
for optimization even if they are turned on as the runtime might 
override a failed assert.


«As developers, we might want to count on a certain kind of 
behavior when an assertion fails. For example, Linux’s BUG_ON() 
is defined to trigger a kernel panic. If we weaken Linux’s 
behavior, for example by logging an error message and continuing 
to execute, we could easily end up adding exploitable 
vulnerabilities.»


So…



Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Michael via Digitalmars-d
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright 
wrote:


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.


Is the part about the optimizer true in D's case? Or is this just 
a theoretical advantage to using asserts that are not evaluated 
in production code but left in?


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread H. S. Teoh via Digitalmars-d
On Wed, Sep 05, 2018 at 03:59:06PM +, Michael via Digitalmars-d wrote:
> On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:
> > 
> > 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.
> 
> Is the part about the optimizer true in D's case? Or is this just a
> theoretical advantage to using asserts that are not evaluated in
> production code but left in?

AFAIK, no optimizer currently actually takes advantage of asserts in
this way.  But Walter has stated that this was his intention all along
when he made asserts a part of the language (as opposed to, e.g., a
macro / standard library call in C).

However, whenever he talks about this, there's always a big controversy
about potential pitfalls, and opinions are divided on this issue.


T

-- 
A linguistics professor was lecturing to his class one day. "In English," he 
said, "A double negative forms a positive. In some languages, though, such as 
Russian, a double negative is still a negative. However, there is no language 
wherein a double positive can form a negative." A voice from the back of the 
room piped up, "Yeah, yeah."


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Meta via Digitalmars-d
On Wednesday, 5 September 2018 at 10:30:46 UTC, Ola Fosheim 
Grøstad wrote:

On Monday, 3 September 2018 at 16:53:35 UTC, Meta wrote:
This battle has been fought over and over, with no movement on 
either side, so I'll just comment that nobody what John Nails 
or anyone else says, my personal opinion is that you're 100% 
wrong on that point :-)


Well, John Regehr seems to argue that you shouldn't use asserts 
for optimization even if they are turned on as the runtime 
might override a failed assert.


«As developers, we might want to count on a certain kind of 
behavior when an assertion fails. For example, Linux’s BUG_ON() 
is defined to trigger a kernel panic. If we weaken Linux’s 
behavior, for example by logging an error message and 
continuing to execute, we could easily end up adding 
exploitable vulnerabilities.»


So…


I don't disagree. I think the only sane way to use asserts as an 
optimization guide is when the program will abort if the 
condition does not hold. That, to me, makes perfect sense, since 
you're basically telling the compiler "This condition must be 
true past this assertion point, because otherwise program 
execution will not continue past this point". You're ensuring 
that the condition specified in the assert is true by definition. 
Not having that hard guarantee but still using asserts as an 
optimization guide is absolutely insane, IMO.


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread H. S. Teoh via Digitalmars-d
On Wed, Sep 05, 2018 at 07:35:46PM +, Meta via Digitalmars-d wrote:
[...]
> I don't disagree. I think the only sane way to use asserts as an
> optimization guide is when the program will abort if the condition
> does not hold. That, to me, makes perfect sense, since you're
> basically telling the compiler "This condition must be true past this
> assertion point, because otherwise program execution will not continue
> past this point". You're ensuring that the condition specified in the
> assert is true by definition.  Not having that hard guarantee but
> still using asserts as an optimization guide is absolutely insane,
> IMO.

Sometimes I wonder about a new primitive called 'assume' for optimizer
hints that *cannot* be (easily) verified at runtime.  The current
meaning of 'assert', to most people, appears to be 'abortIfFalse'.
Walter's definition appears to be 'abortIfFalse' + 'assume'. This
conflation has cost us endless debates on the forum, and I'm wondering
if the way out is to stop conflating the two and acknowledge both as
orthogonal, albeit related, primitives.


T

-- 
"Hi." "'Lo."


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Ola Fosheim Grøstad via Digitalmars-d

On Wednesday, 5 September 2018 at 19:35:46 UTC, Meta wrote:
I don't disagree. I think the only sane way to use asserts as 
an optimization guide is when the program will abort if the 
condition does not hold. That, to me, makes perfect sense, 
since you're basically telling the compiler "This condition 
must be true past this assertion point, because otherwise 
program execution will not continue past this point". You're 
ensuring that the condition specified in the assert is true by 
definition. Not having that hard guarantee but still using 
asserts as an optimization guide is absolutely insane, IMO.


Yes, if you have an advanced optimizer then it becomes dangerous. 
Although a prover could use asserts-with-a-hint for focusing the 
time spent on searching for proofs. It would be way too slow to 
do that for all asserts, but I guess you could single out some of 
the easier ones that are likely to impact performance. That would 
be safe.


There are some cases where "assume" makes sense, of course. For 
instance if you know that a byte-pointer will have a certain 
alignment then you can get the code gen to generate more 
efficient instructions that presume a certain alignment or if you 
can tell the compiler to "assume" that a region of memory is 
filled with zeros then maybe the optimizer can skip 
initialization when creating objects...


And it kinda make sense to be able to autogenerate tests for such 
assumptions for debugging. So it would be like an 
assert-turned-into-assume, but very rarely used...


This would be more of an expert tool for library authors and 
hardcore programmers than a general compiler-optimization.




Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Timon Gehr via Digitalmars-d

On 01.09.2018 22:15, Walter Bright 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.


He does not! John gives two definitions. The first definition is the one 
I want, and he calls it _the best definition_. (I.e., all other 
definitions are inferior.)


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.


The definition you quoted is the /alternative/ definition. He does not 
call it the best definition, and even explains that it can be dangerous. 
He says "it’s not an interpretation that is universally useful". (!)


I don't understand how you can conclude from this that John's view is 
that this should be the default -release behavior of assertions.


Re: John Regehr on "Use of Assertions"

2018-09-05 Thread Timon Gehr via Digitalmars-d

On 02.09.2018 02:47, Nick Sabalausky (Abscissa) wrote:

On 09/01/2018 08:44 PM, Nick Sabalausky (Abscissa) wrote:


    "Are Assertions Enabled in Production Code?"
    "This is entirely situational."
    "The question of whether it is better to stop or keep going when 
an internal bug is detected is not a straightforward one to answer."



All in all, John is very non-committal about the whole thing.


I think you misunderstood what the original post and Guillaumes 
disappointment was about. Walter claims that John agrees that UB on 
failure is the best default -release behavior for assertions. John 
rather explicitly states the opposite in the article.


Being non-committal about whether assertions should be enabled in 
production or not just means that the language should provide both 
options. D does not. Assertions are always enabled: either they are 
checked or they are used as assumptions.


Re: John Regehr on "Use of Assertions"

2018-09-06 Thread Walter Bright via Digitalmars-d

On 9/5/2018 4:55 PM, Timon Gehr wrote:
John rather explicitly states the opposite in 
the article.


I believe that his statement:

"it’s not an interpretation that is universally useful"

is much weaker than saying "the opposite". He did not say it was "never useful".

For example, it is not universally true that airplanes never crash. But it is 
rare enough that we can usefully assume the next one we get on won't crash.


Re: John Regehr on "Use of Assertions"

2018-09-07 Thread Trass3r via Digitalmars-d

On Wednesday, 5 September 2018 at 19:35:46 UTC, Meta wrote:
I think the only sane way to use asserts as an optimization 
guide is when the program will abort if the condition does not 
hold.


Which is the usual behavior of assert.
I'm all for using them to optimize but it's not clear how to do 
that. You can't just blindly turn it into assume since that may 
actually impede optimizations: 
https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic


Re: John Regehr on "Use of Assertions"

2018-09-08 Thread Timon Gehr via Digitalmars-d

On 06.09.2018 23:47, Walter Bright wrote:

On 9/5/2018 4:55 PM, Timon Gehr wrote:

John rather explicitly states the opposite in the article.


I believe that his statement:

"it’s not an interpretation that is universally useful"

is much weaker than saying "the opposite". He did not say it was "never 
useful".

...


Wait, what?

From this it would follow that "UB on failing assert is never useful" 
is the opposite of your stance. Therefore you would think that "UB on 
failing assert is _sometimes_ useful". (I don't have any qualm with 
this, but I would note that this will not be very common, and that a per 
compilation unit switch is a too coarse-grained way to select asserts 
you want to use for optimization, and it also affects @safe-ty therefore 
there should just be a @system __assume primitive _instead_.)


However, not allowing to _disable_ asserts instead of turning them into 
UB is only a good idea if "UB on failing assert is always useful". (I 
totally, utterly disagree with this and we have filled pages of 
newsgroup posts where you were championing this claim.)


So, which is it?


For example, it is not universally true that airplanes never crash. But  > it 
is rare enough that we can usefully assume the next one we get on
won't crash.


So if your stance was: "Airplanes don't crash", and John were to come 
and write an article that said:


"There are two ways to think about airplanes:

1. If they crash, you die. This is the best way to think about airplanes.

2. Another popular way to think about airplanes is that they don't 
crash. However, this interpretation is not universally useful. In fact, 
it can be dangerous if adopted by pilots or engineers."


Then you would conclude: "I am very happy that John agrees with me that 
airplanes don't crash." ?


Re: John Regehr on "Use of Assertions"

2018-09-08 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 09/05/2018 03:35 PM, Meta wrote:


I think the only sane way to use asserts as an 
optimization guide is when the program will abort if the condition does 
not hold. That, to me, makes perfect sense, since you're basically 
telling the compiler "This condition must be true past this assertion 
point, because otherwise program execution will not continue past this 
point". You're ensuring that the condition specified in the assert is 
true by definition. Not having that hard guarantee but still using 
asserts as an optimization guide is absolutely insane, IMO.


I'd certainly agree with this.

Frankly though, I've always found `-release` itself to be a horrible 
thing to use, and I never go anywhere near it. It's a classic case of 
premature optimization, pure and simple - and a dangerous one at that.


IMO the only time an assert should be omitted (note: *an* assert, none 
of this module-level granularity stuff), even in release mode, is when 
you can verify that leaving the assert in would be prohibitively 
expensive: For example, frequent integrity checks on large trees, or 
bounds-checking an inner-loop of a performance-critical codepath.


Removing an assert in release mode is exactly the same as declaring 
"This part can't ever fail, so let's not worry about 'What happens if it 
does fail?'" (if you're THAT certain, why did you write the assert there 
in the first place???). TBH, I'm very surprised that Walter would ever 
be in favor of it.


Re: John Regehr on "Use of Assertions"

2018-09-08 Thread Jonathan M Davis via Digitalmars-d
On Saturday, September 8, 2018 5:31:43 PM MDT Nick Sabalausky (Abscissa) via 
Digitalmars-d wrote:
> On 09/05/2018 03:35 PM, Meta wrote:
> > I think the only sane way to use asserts as an
> > optimization guide is when the program will abort if the condition does
> > not hold. That, to me, makes perfect sense, since you're basically
> > telling the compiler "This condition must be true past this assertion
> > point, because otherwise program execution will not continue past this
> > point". You're ensuring that the condition specified in the assert is
> > true by definition. Not having that hard guarantee but still using
> > asserts as an optimization guide is absolutely insane, IMO.
>
> I'd certainly agree with this.
>
> Frankly though, I've always found `-release` itself to be a horrible
> thing to use, and I never go anywhere near it. It's a classic case of
> premature optimization, pure and simple - and a dangerous one at that.
>
> IMO the only time an assert should be omitted (note: *an* assert, none
> of this module-level granularity stuff), even in release mode, is when
> you can verify that leaving the assert in would be prohibitively
> expensive: For example, frequent integrity checks on large trees, or
> bounds-checking an inner-loop of a performance-critical codepath.
>
> Removing an assert in release mode is exactly the same as declaring
> "This part can't ever fail, so let's not worry about 'What happens if it
> does fail?'" (if you're THAT certain, why did you write the assert there
> in the first place???). TBH, I'm very surprised that Walter would ever
> be in favor of it.

I think that it's all about how you look at it. If you look at assertions as
a way to abort your program because things are so broken that it's too
dangerous to continue, then yeah, removing them is dangerous.

However, if you look at them purely as a debugging tool to help you catch
problems during develepment, that it's no more dangerous to remove
assertions and have the code continue if they would have failed than it is
for any other part of the program to be wrong and continue to operate.
There's nothing special about the code being wrong when an assertion fails
except that it's a case where you put an actual test for it. That code is
broken or not regardless of whether the assertion is actually there. The
assertion is just helping to catch the bug.

I think that that it's this duality of thinking here that's causing a lot of
the problems. Assertions are usually presented as a way to catch bugs during
development (and thus will be removed in production) and _not_ as a way to
catch errors severe enough to abort the program in production. And so a lot
of programmers are going to use them purely as a debugging tool. So, for
assertions to then be used to kill the program in production arguably
doesn't match what they were intended for at all, and when you're adding
assertions with the understanding that they're going to be removed in
production, you're a lot more likely to do stuff like use an assertion to
verify that sort sorted a list correctly, which would be insane to do in
production, whereas if you were using assertions specifically to indicate
that the program _must_ abort if the condition isn't true - even in
production - then you're going to be thinking completely differently about
what you test in assertions.

IIRC, Weka has different types of assertions to differentiate between these
two approaches - one for the cases which absolutely must not happen in
production, and one that's purely for catching problems during developement.
And really, I think that that's probably the right approach.

For many programs, leaving assertions in during production is just going to
needlessly slow the program down, and if the developers know that an
assertion is going to be left in production, they're a lot less likely to
use assertions. On the other hand, there are definitely cases where testing
a conditition is critical enough that you want that test to always be in the
code and for it to abort on failure even in production.

So, maybe what we should do here is take a page from Weka's playbook and add
a function that does something like check a condition and then assert(0) if
it's false and not try to say that assertions should always be left in
production. Sure, someone can choose to not use -relase and leave them in,
but that's often not how assertions are actually used (e.g. last time I
checked std.algorithm's sort really does check that the range is sorted with
an assertion).

- Jonathan M Davis





Re: John Regehr on "Use of Assertions"

2018-09-09 Thread John Carter via Digitalmars-d

On Sunday, 2 September 2018 at 01:55:53 UTC, Walter Bright wrote:

On 9/1/2018 5:47 PM, Nick Sabalausky (Abscissa) wrote:

All in all, John is very non-committal about the whole thing.


He probably got tired of arguing about it :-)


Let's face it, the term "assert" has been poisoned by decades of 
ambiguity.


Come up with another name, (names are free), explicitly define it 
to mean whatever you mean, explicitly define your intentions, and 
use it the way you think it should be used, and _never_ use the 
word "assert" again, .


So much pain side stepped.

ps: I entirely agree with you on asserts, but years of extremely 
painful experience tells me, give up on the word now, but not the 
concept.


Re: John Regehr on "Use of Assertions"

2018-09-09 Thread Ola Fosheim Grøstad via Digitalmars-d

On Sunday, 9 September 2018 at 08:31:49 UTC, John Carter wrote:
On Sunday, 2 September 2018 at 01:55:53 UTC, Walter Bright 
wrote:

On 9/1/2018 5:47 PM, Nick Sabalausky (Abscissa) wrote:

All in all, John is very non-committal about the whole thing.


He probably got tired of arguing about it :-)


Let's face it, the term "assert" has been poisoned by decades 
of ambiguity.


There is really no ambiguity... The terminology is widespread and 
well understood across the field I think.


"assume" means that something is taken as a given fact that has 
already been established by others.


"assert" means that it is something that should be established 
before shipping.


For contracts:

"expects"  (or "requires") means that the input to a function 
should have those properties. (precondition)


"ensures" means that the returned value should always have those 
properties. (postcondition)


Microsoft GSL let you configure pre/post conditions so that you 
either get terminate, throw or (much more dangerous) assume on 
contract violations. They don't seem to provide an option for 
ignoring it.



#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)

#define GSL_CONTRACT_CHECK(type, cond)
 \
(GSL_LIKELY(cond) ? static_cast(0)  
 \
  : 
gsl::details::throw_exception(gsl::fail_fast( 
 \
"GSL: " type " failure at " __FILE__ 
": " GSL_STRINGIFY(__LINE__


#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)

#define GSL_CONTRACT_CHECK(type, cond)
 \
(GSL_LIKELY(cond) ? static_cast(0) : 
gsl::details::terminate())


#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)

#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)

#endif




Re: John Regehr on "Use of Assertions"

2018-09-09 Thread Ola Fosheim Grøstad via Digitalmars-d
On Sunday, 9 September 2018 at 06:27:52 UTC, Jonathan M Davis 
wrote:
So, maybe what we should do here is take a page from Weka's 
playbook and add a function that does something like check a 
condition and then assert(0) if it's false and not try to say 
that assertions should always be left in production.


That's the easy solution, but in real world development things 
get more complicated. Say, if you develop a game maybe you want 
no asserts in your render code, but as many asserts as possible 
in your game logic code...


 It would make sense to defer some way of control to the calling 
context. Especially with templated functions in a very generic 
library that is used across the entire program.




Re: John Regehr on "Use of Assertions"

2018-09-09 Thread John Carter via Digitalmars-d
On Sunday, 9 September 2018 at 09:01:28 UTC, Ola Fosheim Grøstad 
wrote:


Let's face it, the term "assert" has been poisoned by decades 
of ambiguity.


There is really no ambiguity... The terminology is widespread 
and well understood across the field I think.


Ahh, I so, so wish what you said was true. The endless debates in 
this forum, and many other forums across the 'net and sadly, in 
my own workplace, have firmly convinced me...


* The terminology is indeed widespread.
* and well understood across the field
* to mean subtly different and incompatible things to different 
groups of people.


ie. Yes, everybody knows the words, everybody can read the code, 
everybody can find somebody who agrees with his intent and 
meaning but get a large enough group together to try agree on 
what actions, for example, the optimiser should take that are 
implied by that meaning... and flames erupt.


Suddenly you find people don't actually agree on the intent and 
meaning of the code.


Communication is hard, human communication is doubly hard.

I beg humanity to give up on that word "assert" and come up with 
others words and define explicit the intent and meaning and 
implications.


So much pain will be avoided.


Re: John Regehr on "Use of Assertions"

2018-09-10 Thread Ola Fosheim Grøstad via Digitalmars-d

On Sunday, 9 September 2018 at 21:20:11 UTC, John Carter wrote:
ie. Yes, everybody knows the words, everybody can read the 
code, everybody can find somebody who agrees with his intent 
and meaning but get a large enough group together to try 
agree on what actions, for example, the optimiser should take 
that are implied by that meaning... and flames erupt.


Well, it has less to do with "assert" than with how semantics are 
assigned to something that should never occur. But it isn't 
really optimal to hardcode failure semantics in the source code...


Even simple semantics, like whether tests should be emitted in 
release builds is possibly context dependent, so not really 
possible to determine with any level of certainty when writing a 
library reused across many projects.





Re: John Regehr on "Use of Assertions"

2018-09-10 Thread H. S. Teoh via Digitalmars-d
On Sun, Sep 09, 2018 at 12:27:52AM -0600, Jonathan M Davis via Digitalmars-d 
wrote:
[...]
> IIRC, Weka has different types of assertions to differentiate between
> these two approaches - one for the cases which absolutely must not
> happen in production, and one that's purely for catching problems
> during developement.  And really, I think that that's probably the
> right approach.
[...]

On Sun, Sep 09, 2018 at 09:20:11PM +, John Carter via Digitalmars-d wrote:
[...]
> > > Let's face it, the term "assert" has been poisoned by decades of
> > > ambiguity.
[...]
> I beg humanity to give up on that word "assert" and come up with
> others words and define explicit the intent and meaning and
> implications.
> 
> So much pain will be avoided.

Indeed.  D already distinguishes between assert (for catching
programming errors) and enforce (for catching runtime conditions like
bad user input).  It's high time we distinguished between the various
flavors of assert, preferably with new words to avoid the baggage that
has accumulated around 'assert'.

I propose:

- 'assume': aborts on false condition in debug builds, not checked in
  release builds, used as optimizer hint;

- 'insist': aborts on false condition in debug builds, aborts on false
  condition in release builds, used as optimizer hint;

- 'uphold': aborts on false condition in debug builds, aborts on false
  condition in release builds, NOT used as optimizer hint;

- 'allege': logs error and aborts on false condition in debug builds,
  logs error and continues on false condition in release builds, NOT
  used as optimizer hint;


T

-- 
You are only young once, but you can stay immature indefinitely. -- azephrahel


Re: John Regehr on "Use of Assertions"

2018-09-10 Thread Jonathan M Davis via Digitalmars-d
On Monday, September 10, 2018 1:44:22 PM MDT H. S. Teoh via Digitalmars-d 
wrote:
> On Sun, Sep 09, 2018 at 12:27:52AM -0600, Jonathan M Davis via
> Digitalmars-d wrote: [...]
>
> > IIRC, Weka has different types of assertions to differentiate between
> > these two approaches - one for the cases which absolutely must not
> > happen in production, and one that's purely for catching problems
> > during developement.  And really, I think that that's probably the
> > right approach.
>
> [...]
>
> On Sun, Sep 09, 2018 at 09:20:11PM +, John Carter via Digitalmars-d
> wrote: [...]
>
> > > > Let's face it, the term "assert" has been poisoned by decades of
> > > > ambiguity.
>
> [...]
>
> > I beg humanity to give up on that word "assert" and come up with
> > others words and define explicit the intent and meaning and
> > implications.
> >
> > So much pain will be avoided.
>
> Indeed.  D already distinguishes between assert (for catching
> programming errors) and enforce (for catching runtime conditions like
> bad user input).  It's high time we distinguished between the various
> flavors of assert, preferably with new words to avoid the baggage that
> has accumulated around 'assert'.
>
> I propose:
>
> - 'assume': aborts on false condition in debug builds, not checked in
>   release builds, used as optimizer hint;
>
> - 'insist': aborts on false condition in debug builds, aborts on false
>   condition in release builds, used as optimizer hint;
>
> - 'uphold': aborts on false condition in debug builds, aborts on false
>   condition in release builds, NOT used as optimizer hint;
>
> - 'allege': logs error and aborts on false condition in debug builds,
>   logs error and continues on false condition in release builds, NOT
>   used as optimizer hint;

Honestly, that seems like total overkill, and I think that you would have a
_very_ hard sell to get much of anyone to try to use four variants of
assert, regardless of what they were.

Also, why on earth would you suggest _not_ using it as optimizer hint in the
case when it _aborts_ if it's false in both debug and release? At that
point, it's guaranteed to be true if the code gets passed that point.
There's a halfway decent chance that the compiler would end up using that
information for optimizations even without it understanding anything special
about the keyword, simply because it could guarantee that the condition was
true for the code that followed just by seeing that the code aborted if it
was false.

If we were really going to do something to change the situation with
assertions, I'd probably simply argue for adding a function to std.exception
called something like require which was like enforce except that instead of
throwing an exception on failure, it hit assert(0). The compiler should then
be able to safely optimize based on that, and it would provide a standard
way to require that a condition be true regardless of -release. At that
point, there should be no need to optimize based on assertions, and they can
be left as they have been (and as most people expect them to be) as a simple
tool for catching problems during developement. If someone then wants to be
paranoid and leave the assertions in by not compiling with -release, but
that's their choice. Either way, I think that trying to do away with
assertions based on the idea that there isn't always agreement on how they
should be used is overkill, and I think that switching to having something
like four different versions of assertions with new names is definitely
overkill.

IMHO, the biggest problem here is simply that optimizing based on assertions
is dangerous if assertions aren't always left in, and since assertions are
normally explained and used as a tool for catching bugs in development, most
people use them with the idea that they're going to be removed in production
with -release. So, they're not going to be left in production, and
optimizing based on them is just going to be dangerous. That's what needs to
be prevented here.

We don't need a bunch of different types of assertions to solve that
problem. We simply need to _not_ optimize based on assertions, and it would
be a bonus to provide a standard way for people to put checks in their code
that stay with -release, but such a function could trivially be written
right now by anyone who wants it. We don't actually need to do anything
special with the compiler, and we certainly shouldn't need to add separate
helper functions to druntime or Phobos for every stray scenario of leaving
checks in or not that we think someone might want.

- Jonathan M Davis





Re: John Regehr on "Use of Assertions"

2018-09-10 Thread aliak via Digitalmars-d
On Monday, 10 September 2018 at 20:25:21 UTC, Jonathan M Davis 
wrote:
On Monday, September 10, 2018 1:44:22 PM MDT H. S. Teoh via 
Digitalmars-d wrote:

  [...]


Honestly, that seems like total overkill, and I think that you 
would have a _very_ hard sell to get much of anyone to try to 
use four variants of assert, regardless of what they were.


[...]


FWIW I agree that maybe all those is a bit much - would be quite 
confusing to figure out the nuances between 
assert/enforce/assume/insist/uphold/allege.


But, I do see the value in adding an assert flavour that [also] 
aborts in release mode and allows optimizations. And I think the 
proposed assume is a reasonable name for it. And if people want 
it to be left out of release builds they can call "debug 
assume(...)" (compiler is still free to still optimize).


Cheers,
- Ali


Re: John Regehr on "Use of Assertions"

2018-09-10 Thread Meta via Digitalmars-d
On Monday, 10 September 2018 at 20:25:21 UTC, Jonathan M Davis 
wrote:

I propose:

- 'assume': aborts on false condition in debug builds, not 
checked in

  release builds, used as optimizer hint;

- 'insist': aborts on false condition in debug builds, aborts 
on false

  condition in release builds, used as optimizer hint;

- 'uphold': aborts on false condition in debug builds, aborts 
on false

  condition in release builds, NOT used as optimizer hint;

- 'allege': logs error and aborts on false condition in debug 
builds,
  logs error and continues on false condition in release 
builds, NOT

  used as optimizer hint;


Honestly, that seems like total overkill


I'm pretty sure that was sarcasm on H. S. Teoh's part. Of course, 
I can't tell for sure due to Poe's Law.


Re: John Regehr on "Use of Assertions"

2018-09-10 Thread Neia Neutuladh via Digitalmars-d

On Monday, 10 September 2018 at 19:44:22 UTC, H. S. Teoh wrote:
It's high time we distinguished between the various flavors of 
assert, preferably with new words to avoid the baggage that has 
accumulated around 'assert'.


Perhaps we can take some cues from Vigil, the eternally morally 
vigilant programming language, and use 'implore' for 
preconditions (aborts on new strict mode, throws by default) and 
'swear' for other contracts?