assert and static assert and code generation

Steven Schveighoffer schveiguy at gmail.com
Wed Jun 14 14:53:21 UTC 2023


On 6/14/23 9:00 AM, Cecil Ward wrote:
> The compilers should surely be able to use the presence of static 
> asserts to enable better code generation since the direction of some 
> later conditional branches can be known, value ranges can be known, all 
> kinds of potential good stuff. Is that correct?

A static assert is telling the compiler if the condition isn't true at 
compile time, to *halt compilation*. That is, static asserts have no 
bearing on semantic meaning other than to say "this isn't compilable". 
By definition, the compiler knows whether the assert is true or not, so 
there is no "hint" here for better code generation that it couldn't 
already gain from it's own knowledge.

In contrast, an assert is saying a condition should be true *at 
runtime*. This can testify for something that the compiler can't know at 
compile time. In this case, the compiler can take hints from the assert 
to alter code generation (i.e. skip some code that is redundant given 
the assert).

> If assert without the static is implemented as debug assert then unless 
> the compiler makes an exception and does not all the ‘debug’-conditional 
> to simply wipe out the assert entirely the compiler won’t gain the 
> benefit of the information available from an assert.

The compiler can use the hint of the assert whether it generates code to 
perform the assert or not.

> There is of course the difficulty that the non-static assert can not 
> (necessarily) be evaluated at compile-time. But of course the _bool 
> value_ of the assert text-expression is always known.

I'm not sure what you mean here.

> 
> Is there a way of testing whether or not something can be evaluated at 
> compile-time or really requires run-time evaluation? If so, is it 
> something we could use routinely? I could really use this in certain 
> templates, for the case where there are several specialisations that use 
> parameters with special constant values and then there is the 
> ‘otherwise’ default expansion of the template, which has an argument 
> that is not a known compile-time constant.

```d
static if(__traits(compiles, () {enum x = 
someExprToEvalAtCompileTime;})) {...}
```

> So could non-static asserts that do not in fact require run-time 
> evaluation be convertible to an effective status assert, with all the 
> benefits possible in code generation?

A static assert is not evaluated the same as a runtime assert. They 
aren't interchangeable because they aren't solving the same problem.

To give you an example:

```d
void foo1()
{
    if(condThatShouldAlwaysBeTrue)
    {
        performSomeWork();
        return;
    }
    assert(false, "Should not get here");
}

void foo2()
{
    if(condThatShouldAlwaysBeTrue)
    {
        performSomeWork();
        return;
    }
    static assert(false, "Should not get here");
}
```

foo1 will compile and run just fine, as long as the asserted condition 
is always true.

foo2 *will not compile*. Why? Because even to compile `static 
assert(false)` means to halt compilation. It doesn't matter if at 
runtime it will never get there.

-Steve


More information about the Digitalmars-d mailing list