Initialization order in conditional does not match

I see the error

test.chpl:323: In function 'cmplx':
test.chpl:351: error: Initialization order in conditional does not match
test.chpl:352: note: then initializes: re im
test.chpl:359: note: else initializes: im re
  test.chpl:473: called as cmplx(chpl__tuple_arg_temp0: (real(64),imag(64)))
note: generic instantiations are underlined in the above callstack

in the following code (where I have identified Line 351).

I have a block with an ... if then {} else if then {} else {} clause and the compiler complains if I initialise variables in the various blocks in different orders. I cannot understand why.

Is this a Github issue or a Discourse topic?

    var re : Real, im : Real;

    inline proc zeroNaN(x : Real)
    {
        return if x == x then x else zero;
    }

    if _r > _inf then // isNaN(r) || r < 0
    {
        im = nan;
        re = nan;
    }
    else if _ua < _inf then // isFinite(theta) // Line 351 is HERE
    {
        const y = exp(t);

        re = zeroNaN(r * y.re);
        im = zeroNaN(r * y.im);
    }
    else //
    {
        im = if _ua > _inf then u else nan;
        re = if _ra == _inf then r else im;
    }
    // wrap up
    {
        var z : Cmplx;

        z.im = im; z.re = re;
        return z;
    }

Hi @damianmoz - you are running into a feature called Split Init -- see Variables — Chapel Documentation 1.31 if you want to read about it. The split init feature is intended to minimize unnecessary assignments (which are more or less unnecessary copies). However, it comes with a rule that the initialization order has to match between the then and else branches of a conditional. These unnecessary assignments and copies are almost certainly irrelevant for variables just containing a floating point number.

If you are working with simple values (not arrays or records etc) then easy way to work around this issue would be to initialize re and im to 0 before the conditional. Depending on how you declared them, it might be as simple as writing something like var re: real(32) = 0.0; var im: imag(32) = 0.0i;

Another option is to introduce another variable for the else block:

else
{
   const imTmp = if _ua > _inf then u else nan;
   re = if _ra == _inf then r else imTmp;
   im = imTmp;
}
1 Like

Thanks for the background. I introduced another variable in the else block.