Helping the compiler with assumptions while using exceptions

Timon Gehr timon.gehr at gmx.ch
Mon May 30 14:39:10 PDT 2011


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. 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.

Timon


More information about the Digitalmars-d-learn mailing list