Helping the compiler with assumptions while using exceptions

Jonathan M Davis jmdavisProg at gmx.com
Mon May 30 14:55:24 PDT 2011


On 2011-05-30 14:39, Timon Gehr wrote:
> Jonathan M Davis wrote:
> > On 2011-05-30 12:49, simendsjo wrote:
> >> I'm having some problems trying to get the best of both worlds here.
> >> 
> >> void f(Class c) {
> >> 
> >>    assert(c != null);
> >>    // use c
> >> 
> >> }
> >> 
> >> In this example, we tell the compiler that c is never able to be null.
> >> The compiler can use assertions like this for optimizations (not sure if
> >> dmd does this though).
> >> 
> >> But assert is only a debugging tool.
> >> Say we wanted to have this check at runtime too - just in case - so we
> >> can fail where the problem is.
> >> 
> >> So we do this:
> >> 
> >> void f(Class c) {
> >> 
> >>    enforce(c != null);
> >>    // use c
> >> 
> >> }
> >> 
> >> But now the compiler has no idea c will never be null later on (or does
> >> it...?).
> >> 
> >> We could always do this:
> >> 
> >> void f(Class c) {
> >> 
> >>    assert(c != null);
> >>    enforce(c != null);
> >>    // use c
> >> 
> >> }
> >> 
> >> But this is overly verbose.
> 
> Actually, what you have written does not make sense. Correct would be:
> void f(Class c) {
>    enforce(c != null);
>    assert(c != null); //if c is null, control can never reach this
> instruction. // use c
> }
> 
> You cannot move assert into the contract in your use case, because it is
> not a contract. It will be valid to call your function with a null
> reference, it will just throw an exception.
> 
> >> Or is this not a problem at all? E.g. Use enforce for runtime checks -
> >> the compiler understands them/won't use asserts for optimizations
> >> anyway?
> 
> Currently, DMD does not use assertions or exceptions for optimization of
> code, but it could.
> 
> > assert and enforce serve two very different purposes. assert is used for
> > code verification. You can't assume that it's always be there, because
> > it might be compiled out. As such, the compiler is not going to use it
> > for any optimizations. If an assertion fails, there's a bug in your
> > program. It's used to detect bugs.
> 
> And to give hints to the compiler. This is what his question was about.
> 
> > enforce and exceptions, on the other hand, are _not_ intended for bug
> > detection. They are for error handling. They're generally used in cases
> > where you want to ensure that something is true but where you can't
> > guarantee it (such as when dealing with user input or the file system).
> > You throw an exception if the condition isn't true, and then you deal
> > with it however is appropriate. Generally-speaking, an exception does
> > _not_ indicate a bug. It indicates an error, but that doesn't mean that
> > there's anything wrong with your program. Rather, there was a problem
> > with its input.
> > [snip.]
> 
> I think he understands most of that.

The fact that he was talking about essentially swapping out enforce for assert 
implied that he doesn't.

> His question was whether or not the
> compiler can use enforcements to optimize code. Eg: (silly example)
> 
> int foo(int x){
>     enforce(x==0);
>     return x*extremely_costly_pure_function_call();
> }
> 
> A smart compiler could optimize the function to
> 
> int foo(int x){
>     enforce(x==0);
>     return 0;
> }
> 
> The answer is yes, theoretically it could. (It would either have to have
> some very advanced code analysis caps, or would just have to treat enforce
> specially.) DMD does not currently use either enforcements or assertions
> to generate optimized code, so using an enforcement is sufficient.

I'd be very surprised to see the compiler ever optimize code based on assert 
or enforce statement. It's unlikely to do so based on assert simply because 
the assertion is going to be compiled out. I think that there's a high chance 
that optimizing based on an assertion that is removed in release mode would 
actually be violating the guarantees of assert, since then the code without it 
wouldn't act the same. But you'd have to ask Walter on that one. As for 
enforce, it'll never happen because enforce is a library function, and the 
compiler doesn't know anything about it. So, I wouldn't expect to ever seen 
any compiler optimzations based on assert or enforce.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list