New Issue: copy elision when LHS and RHS have different types

17089, “mppf”, “copy elision when LHS and RHS have different types”, “2021-02-05T11:42:58Z”

We have copy elision that applies when the RHS initializing a variable is not used again. However the compiler does not currently allow copy elision when the types are different.

One test that relies on this behavior is test/studies/shootout/nbody/sidelnik/nbody_orig_1.chpl.

After PR #16802, array literals are created with chpl__buildArrayExpr using the in intent. The result is that the code

  var bodies: [0..#NBODIES] borrowed Planet = [ new Planet(...), ... ]

creates a RHS temporary array of owned - let’s call it tmpArray. tmpArray is destroyed at the end of the block (and the temporaries for the individual new call results are moot at this point since they are nil from having been transferred out of).

This was working as of PR #16802 because the array bodies array was created by copy-initializing from tmpArray. However, if this is changed to move-initialization, we get a use-after-free (because the borrowed array refers to something that is destroyed).

Should copy elision apply when the LHS and RHS types in the initialization differ?

Arguments in favor:

  • It makes the copy elision more consistent if it is type independent

Arguments against:

  • When the types differ, it’s more of a cast operation, and “stealing” the memory from the RHS will probably not be possible

The language specification does not say anything about a type constraint for copy elision. So, if the answer is “yes”, the implementation needs adjustment, and if the answer is “no”, the spec needs adjustment.