Asserts and side effects

Denis Koroskin 2korden at gmail.com
Mon Nov 30 03:15:32 PST 2009


On Mon, 30 Nov 2009 13:52:48 +0300, Lars T. Kyllingstad  
<public at kyllingen.nospamnet> wrote:

> The following is a quote from a comment in the Reddit post about asserts  
> that Walter just linked to:
>
>      "Asserts are not without pitfalls, though. If you aren't careful,
>       what to put in the asserts, the program could behave differently"
>
> A trivial example of this is:
>
>      int i;
>      write(i);
>      assert (++i == 1);
>      write(i);
>
> Normally, this program prints "01", but in release mode it prints "00".  
> Asserts should never change the behaviour of a program, but currently it  
> is up to the programmer to verify that this is in fact the case.
>
> Would it be possible (and desirable) for the D compiler to statically  
> check that asserts have no side effects?
>
> -Lars

Compiler must do full code flow analysis to do that:

bool foo(); // no body or body is very complicated

void main()
{
     assert(foo()); // okay to call or not?
}

I believe this is doable with introduction of a new attribute -  
@hasNoSideEffects (shorter name would be better) with the following rules:

- @hasNoSideEffects functions cannot modify variables outside of a  
function scope. It means that they can read globals, but can not get a  
non-const reference (or pointer) to them.

- @hasNoSideEffects can only call other @hasNoSideEffects functions

- Body of an assert check has a @hasNoSideEffects attribute, and follows  
the same rules.

@pure is a subclass of @hasNoSideEffects. @hasNoSideEffects functions are  
also very useful for various performance optimizations.

I think it is as valid attribute as @pure (even though it might affect  
code generation outside of a function body due to open optimization  
opportunities).

Perhaps @pure semantics should be changed to @hasNoSideEffects (i.e. allow  
non-invariant input arguments and allow accessing globals).

It will lose a memoization ability, but to be honest I don't think  
memoization needs to be implemented based on @pure attribute alone. For  
example, std.math.pow() is @pure, but is it worth memoizing? I think it's  
programmer who should decide what functions are expensive enough to be  
memoized, and these should be marked as such explicitly (@memoizable, or  
something).



More information about the Digitalmars-d mailing list