July 28, 2014
On Monday, 28 July 2014 at 13:31:50 UTC, Daniel Murphy wrote:
> The compiler is allowed to not check assertions in release mode.  This is because a program that would fail an assertion is a broken program, and by specifying -release you are telling the compiler to assume all assertions pass.  I don't see any reason the compiler shouldn't be allowed to change code-gen based on asserts.

In that case I will write my own assert() that doesn't have this behaviour. Nobody who cares about program verification and correctness will touch this.

It means that you have to formally prove every single assert() to be correct. This is HARD. Hoare logic is _very_ difficult even for simple programs.

assert() is no guarantee for correctness, it is basically a break-point check. A sloppy request from the programmer to check some constraint that possibly could be overspecified, and that could silently pass. The the optimizer might assume that "length<1024" etc and create all kinds of problems.

Assert() are useful debugging tools, but not a codegen feature. A good debugger could allow you to turn them on/off or let you continue after hitting one. That's useful.
July 28, 2014
"Ola Fosheim Grøstad" " wrote in message news:scibhjsiolgykujqxwbx@forum.dlang.org...

> In that case I will write my own assert() that doesn't have this behaviour. Nobody who cares about program verification and correctness will touch this.

Yes.

> assert() is no guarantee for correctness, it is basically a break-point check. A sloppy request from the programmer to check some constraint that possibly could be overspecified, and that could silently pass. The the optimizer might assume that "length<1024" etc and create all kinds of problems.

Yes, writing code wrong can result in the wrong thing happening.  A non-release build will always retain the asserts.

> Assert() are useful debugging tools, but not a codegen feature. A good debugger could allow you to turn them on/off or let you continue after hitting one. That's useful.

If this is what you want you shouldn't be using assert.  This is not what assert means in D. 

July 28, 2014
On Monday, 28 July 2014 at 13:50:29 UTC, Daniel Murphy wrote:
> Yes, writing code wrong can result in the wrong thing happening.  A non-release build will always retain the asserts.

No, writing wrong code is one thing.

Having a single typo in a constraint-test cause memory unsafety undetected is a disaster. And many such typos _will_ go undetected.

Let's say you want to test "divisor >= 0", but end up with "divisor != 0" => division_by_zero failure even if the code is correct.

Adding assert() should increase quality, not decrease it. Adding asserts will increase the probability of wrong constraints entering the codebase. That means with the regime indicated here you should write as few assert() statements as possible.

>> Assert() are useful debugging tools, but not a codegen feature. A good debugger could allow you to turn them on/off or let you continue after hitting one. That's useful.
>
> If this is what you want you shouldn't be using assert.  This is not what assert means in D.

Where in the spec does it say that assert is a tool for specifying optimization constraints?

That would be a disaster.
July 28, 2014
"Ola Fosheim Grøstad" " wrote in message news:ejbwjvylulclchhehlnw@forum.dlang.org...

> No, writing wrong code is one thing.
>
> Having a single typo in a constraint-test cause memory unsafety undetected is a disaster. And many such typos _will_ go undetected.

Sure, because having single typos in other parts of your code causing memory unsafety are totally not a disaster.  And those never go undetected.

>
> Let's say you want to test "divisor >= 0", but end up with "divisor != 0" => division_by_zero failure even if the code is correct.

Let's say you want to add two numbers, but instead of writing 'a + b' you write 'a - b'!!!!  The program fails even though you totally meant to write the correct code.

>
> Adding assert() should increase quality, not decrease it. Adding asserts will increase the probability of wrong constraints entering the codebase. That means with the regime indicated here you should write as few assert() statements as possible.

I disagree.  If you do not want your assertion removed then don't compile with -release.

> Where in the spec does it say that assert is a tool for specifying optimization constraints?

Where in the spec does it say assert is a tool for inserting breakpoints?

Asserts are a tool for conveying to the compiler certain conditions that you expect to be true. 

July 28, 2014
On Monday, 28 July 2014 at 15:07:07 UTC, Daniel Murphy wrote:
> Let's say you want to add two numbers, but instead of writing 'a + b' you write 'a - b'!!!!  The program fails even though you totally meant to write the correct code.

You are trolling me. :-[

Verification is not specification. D stands for DOOMED if this goes through.

If asserts were used as optimization constraints then the viral nature of this will undermine all codebases that use libraries. Make one frigging function call, pass through a overstated assert and all your precious handcrafted if-checks evaporates without notice. Goodbye protection against division-by-zero, NaN, out-of-bounds checks etc.

> I disagree.  If you do not want your assertion removed then don't compile with -release.

Asserts are there to harness programs, not to weaken them.

> Where in the spec does it say assert is a tool for inserting breakpoints?

It says they inject checks. Not semantic constraints. They are not verified.

> Asserts are a tool for conveying to the compiler certain conditions that you expect to be true.

No, assert() is a tool for testing that certain constraints hold at RUNTIME, because you failed to prove them.



July 28, 2014
On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad wrote:
> If asserts were used as optimization constraints

all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it.

bool foo(int a)
{
    //let's handwrite a simple assert
    if(a >= 0)
    {
        exit(EXIT_FAILURE);
    }
    //and then do something.
    return a < 0;
}

Of course the compiler is free to rewrite that as

bool foo(int a)
{
    if(a >= 0)
    {
        exit(EXIT_FAILURE);
    }
    return true;
}

Why should the situation be different if I use the builtin `assert` instead?
July 28, 2014
Daniel Murphy:

> One murky area is that assert(0) is currently used to mean both 'unreachable' and 'unimplemented'.  It's unclear what the compiler is allowed to do with an assert(0) in release mode.

I'd still like to have a halt() in D, and have assert(0) with the same semantics of the other asserts. In many cases when you have a different feature it's good to also give it a different name.

Bye,
bearophile
July 28, 2014
On Monday, 28 July 2014 at 15:52:23 UTC, John Colvin wrote:
> On Monday, 28 July 2014 at 15:20:44 UTC, Ola Fosheim Grøstad wrote:
>> If asserts were used as optimization constraints
>
> all available code is fair game as optimisation constraints. What you are asking for is a special case for `assert` such that the optimiser is blind to it.
>
> bool foo(int a)
> {
>     //let's handwrite a simple assert
>     if(a >= 0)
>     {
>         exit(EXIT_FAILURE);
>     }
>     //and then do something.
>     return a < 0;
> }
>
> Of course the compiler is free to rewrite that as
>
> bool foo(int a)
> {
>     if(a >= 0)
>     {
>         exit(EXIT_FAILURE);
>     }
>     return true;
> }
>
> Why should the situation be different if I use the builtin `assert` instead?

admittedly this requires knowing that exit() won't return control back to the function. With a dummy return it will still work though:

bool foo(int a)
{
    //let's handwrite a simple assert
    if(a >= 0)
    {
        exit(EXIT_FAILURE);
        return false; //dummy return
    }
    //and then do something.
    return a < 0;
}
July 28, 2014
"bearophile"  wrote in message news:tijfjtihtubozpjojgvl@forum.dlang.org...

> I'd still like to have a halt() in D, and have assert(0) with the same semantics of the other asserts. In many cases when you have a different feature it's good to also give it a different name.

Yes, me too.  The compiler could then still insert halt in place of assert(0), but it wouldn't be forced to treat them as a halt in release mode.  It may be too late to change assert's behaviour. 

July 28, 2014
"Ola Fosheim Grøstad" " wrote in message news:cgljkngsjwkspfixdfgy@forum.dlang.org...

> On Monday, 28 July 2014 at 15:07:07 UTC, Daniel Murphy wrote:
> > Let's say you want to add two numbers, but instead of writing 'a + b' you write 'a - b'!!!!  The program fails even though you totally meant to write the correct code.
>
> You are trolling me. :-[

Yes.  I think you'll find advanced optimizers are already doing this sort of thing to your code, when it decides code is unreachable.

Enabling optimizations can make code-gen unpredictable, especially when used on broken code.  In C/C++ this is often due to undefined behaviour.  Using assert to pass arbitrary information to the optimizer would allow for some fantastic opportunities.

Just imagine how close to perfection the compiler can get with these constraints:

void vectorizedFunction(int* a, int* b, size_t len)
in
{
   assert(noOverlap(a, b, len));
   assert(len % 16 == 0);
}
body
{
   < some kind of code that can benefit from vectorization >
}

Sure, we could add a new construct (ie 'assume') to the language, and use that to pass information.  But are they really different?

Assert says 'the program is in error if this is not true'.  -release says 'compile my program as if it has no errors'.

These two combined give the compiler a huge amount of power.