Schrodinger's CTFE

Steven Schveighoffer schveiguy at gmail.com
Wed Jul 15 20:33:23 UTC 2020


I found a weird workaround to the "Unreachable code" problem.

In a nutshell, code that is sometimes reachable given the correct 
template parameters can be flagged as unreachable when instantiated with 
different ones.

An example (compile with -w):

int foo(bool x)()
{
    if(x) return 1;
    return 2;
}

void main()
{
    auto x = foo!false(); // ok
    auto y = foo!true(); // Warning: "return 2;" is unreachable
}

A weird solution is to declare a boolean value somewhere as always true, 
and use it to "break" free from the constant folding:

int foo(bool x)()
{
    auto b = true;
    if(x && b) return 1;
    return 2;
}

The boolean will likely be removed by the optimizer, but it's kind of a 
clunky solution.

However, we also have a special boolean __ctfe that is treated as a 
runtime variable for things like checking reachability, but treated as a 
compile-time constant for code generation (so truly unreachable code is 
simply removed instead of being flagged for unreachability).

This also works, but is only good for compile time or runtime (depending 
on your intentions for foo):

int foo(bool x)()
{
    if(x && __ctfe) return 1; // or !__ctfe for runtime
    return 2;
}

I was going to ask if we could have another special variable that is 
like __ctfe in these respects, but is *always* true for both runtime and 
compile time, but I actually found out a weird trick. This works, and 
does the same thing at both runtime and compile time, plus will only 
generate one branch for the runtime (without even the optimizer turned on):

int foo(bool x)()
{
    if(x && (__ctfe || !__ctfe)) return 1;
    return 2;
}

I think this is a way to fix some of those static foreach loops with 
returns which can have these reachability problems. Only, it's really 
verbose and ugly. Maybe we still should have that other variable?

-Steve


More information about the Digitalmars-d mailing list