assert semantic change proposal

David Bregman via Digitalmars-d digitalmars-d at puremagic.com
Tue Aug 5 15:56:56 PDT 2014


On Tuesday, 5 August 2014 at 18:19:00 UTC, Jeremy Powers via 
Digitalmars-d wrote:
> This has already been stated by others, but I just wanted to 
> pile on - I
> agree with Walter's definition of assert.
>
> 2. Semantic change.
>> The proposal changes the meaning of assert(), which will 
>> result in
>> breaking existing code.  Regardless of philosophizing about 
>> whether or not
>> the code was "already broken" according to some definition of 
>> assert, the
>> fact is that shipping programs that worked perfectly well 
>> before may no
>> longer work after this change.
>
>
>
> Disagree.
> Assert (as I always understood it) means 'this must be true, or 
> my program
> is broken.'  In -release builds the explicit explosion on a 
> triggered
> assert is skipped, but any code after a non-true assert is, by 
> definition,
> broken.  And by broken I mean the fundamental constraints of 
> the program
> are violated, and so all bets are off on it working properly.
> A shipping program that 'worked perfectly well' but has 
> unfulfilled asserts
> is broken - either the asserts are not actually true 
> constraints, or the
> broken path just hasn't been hit yet.

This is the 'already broken' argument, which I mentioned in the 
quote above.

This kind of change could never be made in C or C++, because 
there is too much legacy code that depends on it. Perhaps D can 
still afford to break this because it's still a young language. 
That is a strength of young languages. If you believe in this 
case that the upside justifies the breakage, by all means, just 
say so and accept the consequences. Don't try to escape 
responsibility by retroactively redefining previously working 
code as broken :)

>
> Looking at the 'breaking' example:
>
> assert(x!=1);
> if (x==1) {
>  ...
> }
>
> If the if is optimized out, this will change from existing 
> behaviour.  But
> it is also obviously (to me at least) broken code already.  The 
> assert says
> that x cannot be 1 at this point in the program, if it ever is 
> then there
> is an error in the program.... and then it continues as if the 
> program were
> still valid.  If x could be one, then the assert is invalid 
> here.  And this
> code will already behave differently between -release and 
> non-release
> builds, which is another kind of broken.

Not everything that breaks will be so obvious as that. It can get 
much more hairy when assumptions propagate across multiple levels 
of inlining.

Also, some code purposely uses that pattern. It is (or rather, 
was) valid for a different use case of assert.

>
> 3a. An alternate statement of the proposal is literally "in 
> release mode,
>> assert expressions introduce undefined behavior into your code 
>> in if the
>> expression is false".
>>
>
> This statement seems fundamentally true to me of asserts 
> already,
> regardless of whether they are used for optimizations.  If your 
> assert
> fails, and you have turned off 'blow up on assert' then your 
> program is in
> an undefined state.  It is not that the assert introduces the 
> undefined
> behaviour, it is that the assert makes plain an expectation of 
> the code and
> if that expectation is false the code will have undefined 
> behaviour.
>

This is not the standard definition of undefined behavior.

With regular assert, execution is still well defined. If you want 
to know what happens in release mode when the assert condition is 
not satisfied, all you need to do is read the source code to find 
out.

With assume, if the condition is not satisfied, there is no way 
to know what will happen. _anything_ can happen, it can even 
format your hard drive. That's true undefined behavior.

>
> 3b. Since assert is such a widely used feature (with the 
> original
>> semantics, "more asserts never hurt"), the proposal will 
>> inject a massive
>> amount of undefined behavior into existing code bases, greatly 
>> increasing
>> the probability of experiencing problems related to undefined 
>> behavior.
>>
>
> I actually disagree with the 'more asserts never hurt' 
> statement.  Exactly
> because asserts get compiled out in release builds, I do not 
> find them very
> useful/desirable.  If they worked as optimization hints I might 
> actually
> use them more.
>
> And there will be no injection of undefined behaviour - the 
> undefined
> behaviour is already there if the asserted constraints are not 
> valid.

This uses your own definition of UB again, it isn't true for the 
regular definition.

>  Maybe if the yea side was consulted, they might easily agree 
> to an
>> alternative way of achieving the improved optimization goal, 
>> such as
>> creating a new function that has the proposed semantics.
>>
>
> Prior to this (incredibly long) discussion, I was not aware 
> people had a
> different interpretation of assert.  To me, this 'new 
> semantics' is
> precisely what I always thought assert was, and the proposal is 
> just
> leveraging it for some additional optimizations.  So from my 
> standpoint,
> adding a new function would make sense to support this 
> 'existing' behaviour
> that others seem to rely on - assert is fine as is, if the 
> definition of
> 'is' is what I think it is.

That doesn't mean you don't have buggy asserts in your code, or 
buggy assers in libraries you use (or the standard library), so 
you are not immune from undefined behavior.


More information about the Digitalmars-d mailing list