Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

void initialisation of out parameters #19303

Open
dlangBugzillaToGithub opened this issue Aug 20, 2017 · 3 comments
Open

void initialisation of out parameters #19303

dlangBugzillaToGithub opened this issue Aug 20, 2017 · 3 comments

Comments

@dlangBugzillaToGithub
Copy link

Nicholas Wilson (@thewilsonator) reported this on 2017-08-20T01:17:12Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=17765

CC List

  • Илья Ярошенко
  • Steven Schveighoffer (@schveiguy)

Description

Out variables are always initialised, but when they are large static arrays this incurs a performance penalty. For declaration of regular variables we have = void to stop default initialisation. This does not work for out variables. This ER suggests to make `i` valid syntax to suppress initialisation of the out variable.  

enum M = 2600;
void f() {
    float[M] mean = void; // works as expected, mean is left uninitialised
}

void g(out float[M][M] corr) // works but assigns twice
{
    corr[] = float.init; // compiler inserted

    // assign to each value of corr
}

// only assigns once but does not signal intention like out does
// also is valid to read from `corr` as opposed to write only like `g`
void h(ref float[M][M] corr) 
{
    // assign to each value of corr
}

//Error: found ')' when expecting '.' following void
void i(out float[M][M] corr = void)
{
    // assign to each value of corr
}
@dlangBugzillaToGithub
Copy link
Author

schveiguy (@schveiguy) commented on 2017-08-21T14:45:27Z

In the case of out variables, one of the reasons the init is done is to ensure that the data is all written to.

2 things:

1. If the compiler can prove that the out variable is completely written in all paths, then the initial write can be removed (could be happening already).
2. If the out = void syntax is accepted, and not all the data is written, then this should really be an error.

Both require advanced flow analysis, and may not be possible in all cases, so the result is that in cases where =void is used, not writing all the data is going to be UB.

Another issue is that the current grammar/syntax defines =X to mean "pass X as parameter if none specified". =void looks weird, and it also doesn't fit the grammar if you have required parameters after it.

I was wondering if this could more of an implementation detail in the function itself.

i.e.:

void g(out float[M][M] corr)
{
    corr = void; // disables the initial write
}

This shouldn't be allowed in @safe code.

@dlangBugzillaToGithub
Copy link
Author

iamthewilsonator commented on 2017-08-22T00:38:42Z

Yeah the compiler was not able to determine that all values were assigned despite there being no conditional logic for the initialisation:

foreach(i; 0 .. M-1)
{
    corr[i][i] = 1.0;
    for (auto j = i+1; j < M; j++)
    {
        corr[i][j] = 0.0;
        for (auto k = 0; k < N; k++)
        corr[i][j] += data[k][i] * data[k][j];
        corr[j][i] = corr[i][j];
    }
}
foreach(i; 0 .. M) corr[M-1][i] = 0.0;
corr[M-1][M-1] = 1.0;

>I was wondering if this could more of an implementation detail in the function itself.
>
> i.e.:
>
> void g(out float[M][M] corr)
> {
>     corr = void; // disables the initial write
> }

That would also work and would probably be less effort in the compiler and less confusing.

> This shouldn't be allowed in @safe code.

Definitely.

@dlangBugzillaToGithub
Copy link
Author

ilyayaroshenko commented on 2020-06-19T07:44:20Z

related issue https://issues.dlang.org/show_bug.cgi?id=20957

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant