Thread overview
Assert allowed to have side effects?
May 29, 2011
simendsjo
May 29, 2011
Stewart Gordon
May 29, 2011
bearophile
May 29, 2011
simendsjo
May 30, 2011
Stewart Gordon
May 31, 2011
Jonathan M Davis
May 31, 2011
David Nadlinger
May 31, 2011
bearophile
May 29, 2011
The documentation for assert, http://www.digitalmars.com/d/2.0/expression.html#AssertExpression, states that it's an error if the assert expression contains side effects, but it doesn't seem the compiler is enforcing this.

module assert_sideeffect;
bool b;
bool f() { b = !b; return b; }
void main() {
    assert(f()); // oops.. changes b in debug mode
    if(!b) { // true only in release
        assert(0);
    }
}

dmd -g -w -wi -debug -run assert_sideeffect
// no output

dmd -g -w -wi -release -run assert_sideeffect
object.Error: assert(0) or HLT instruction
May 29, 2011
On 29/05/2011 09:44, simendsjo wrote:
> The documentation for assert,
> http://www.digitalmars.com/d/2.0/expression.html#AssertExpression, states that it's an
> error if the assert expression contains side effects, but it doesn't seem the compiler is
> enforcing this.

There are places where the spec fails to make a clear distinction between illegal code and incorrect code that the compiler may reject if it's smart enough.

The point of asserts is to check that the code is working correctly.  By the time you come to release your software, you know that it's working correctly, and so the compiler ignores asserts in release mode.  So the onus is on you to make sure the asserts don't have side effects.

> module assert_sideeffect;
> bool b;
> bool f() { b = !b; return b; }
> void main() {
> assert(f()); // oops.. changes b in debug mode
<snip>

It doesn't depend on debug mode.  It depends on release mode.  They're two independent compiler switches.

Stewart.
May 29, 2011
Stewart Gordon:

> There are places where the spec fails to make a clear distinction between illegal code and incorrect code that the compiler may reject if it's smart enough.

In D there are pure functions, so I think it's not too much hard for it to tell apart when the contents of an assert() are pure or not.
My opinion is that the D compiler has to enforce purity inside assert(), to avoid bugs.

Bye,
bearophile
May 29, 2011
On 29.05.2011 15:03, bearophile wrote:
> In D there are pure functions, so I think it's not too much hard for it to tell apart when the contents of an assert() are pure or not.
> My opinion is that the D compiler has to enforce purity inside assert(), to avoid bugs.

http://d.puremagic.com/issues/show_bug.cgi?id=6074

May 30, 2011
On 29/05/2011 14:03, bearophile wrote:
> Stewart Gordon:
>
>> There are places where the spec fails to make a clear distinction between illegal code and
>> incorrect code that the compiler may reject if it's smart enough.
>
> In D there are pure functions, so I think it's not too much hard for it to tell apart
> when the contents of an assert() are pure or not.
> My opinion is that the D compiler has to enforce purity inside assert(), to avoid bugs.

Only if purity rules are relaxed.  AIUI, one of the restrictions at the moment is that in a pure function only immutable data can be accessed.  As long as this restriction remains in place, adding the restriction of purity to asserts would erode their usefulness.

Stewart.
May 31, 2011
On 2011-05-30 16:34, Stewart Gordon wrote:
> On 29/05/2011 14:03, bearophile wrote:
> > Stewart Gordon:
> >> There are places where the spec fails to make a clear distinction between illegal code and incorrect code that the compiler may reject if it's smart enough.
> > 
> > In D there are pure functions, so I think it's not too much hard for it
> > to tell apart when the contents of an assert() are pure or not.
> > My opinion is that the D compiler has to enforce purity inside assert(),
> > to avoid bugs.
> 
> Only if purity rules are relaxed.  AIUI, one of the restrictions at the moment is that in a pure function only immutable data can be accessed.  As long as this restriction remains in place, adding the restriction of purity to asserts would erode their usefulness.

That's not quite true. Pure functions cannot access global or static variables which are not immutable. However, they can access mutable data in objects just fine. However, unless their parameters are all either immutable or implicitly convertible to immutable, then they are weakly pure and cannot be optimized out like strongly pure functions can (the immutability of the function's parameters being the deciding factor for weak vs strong).

Really, the problem with enforcing that assertions have pure expressions is the fact that there is a _ton_ of valid code which will never be able to be pure, and it would be _highly_ annoying to not be able to call it in assertions. Many unittest blocks would double in size, because they would have to save all of their results as local variables and test the variables instead of just testing the expressions directly. It would be horrific if you couldn't put non-pure functions in assertions. Granted, the programmer needs to be somewhat intelligent about what they put in assertions (any calls which actually have side effects are likely to cause bugs due to the fact that the code changes when the assertions go away), but using purity as a way to enforce a lack of side effects would have _far_ too many negative effects to be worthwhile.

Regardless, Walter has already shot down the idea ( http://d.puremagic.com/issues/show_bug.cgi?id=6074 ), and I _really_ doubt anyone is going to be able to convince him.

- Jonathna M Davis
May 31, 2011
On 5/31/11 1:34 AM, Stewart Gordon wrote:
> On 29/05/2011 14:03, bearophile wrote:
>> Stewart Gordon:
>>
>>> There are places where the spec fails to make a clear distinction
>>> between illegal code and
>>> incorrect code that the compiler may reject if it's smart enough.
>>
>> In D there are pure functions, so I think it's not too much hard for
>> it to tell apart
>> when the contents of an assert() are pure or not.
>> My opinion is that the D compiler has to enforce purity inside
>> assert(), to avoid bugs.
>
> Only if purity rules are relaxed. AIUI, one of the restrictions at the
> moment is that in a pure function only immutable data can be accessed.
> As long as this restriction remains in place, adding the restriction of
> purity to asserts would erode their usefulness.
>
> Stewart.

Nope, since the new, relaxed purity rules (originally proposed by Don, IIRC) were implemented in DMD 2.050, this is no longer the case. »Weakly pure« functions take mutable parameters and can access them (this also applies to the hidden this reference), while »strongly pure« functions only operate on immutable values. There is no syntactic distinction between them, both are annotated by the »pure« keyword, it just depends on the parameter types.

David
May 31, 2011
Stewart Gordon:

> Only if purity rules are relaxed.  AIUI, one of the restrictions at the moment is that in a pure function only immutable data can be accessed.  As long as this restriction remains in place, adding the restriction of purity to asserts would erode their usefulness.

You are of course right, I didn't think enough about this.
So something different than purity is needed here, something like a "constview" (I have suggested something similar time ago, for different purposes), this means it's allowed to read mutable data in the outer scopes, but can't modify it. To work well this too has to become transitive, like pure and nothrow. And this is probably too much complexity added. So no game :-)

Bye and thank you,
bearophile