www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Assert allowed to have side effects?

reply simendsjo <simen.endsjo pandavre.com> writes:
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
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
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

It doesn't depend on debug mode. It depends on release mode. They're two independent compiler switches. Stewart.
May 29 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
next sibling parent simendsjo <simen.endsjo pandavre.com> writes:
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 29 2011
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
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 30 2011
next sibling parent David Nadlinger <see klickverbot.at> writes:
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 30 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
May 30 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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 30 2011