Confusing behaviour of array member assignment when calling local function

Sahan Fernando sahan.h.fernando.alt at gmail.com
Sat Jan 4 23:11:58 UTC 2025


Hello all,

I've encountered an unexpected behaviour in the D language, where 
assigning the result of a function that grows an array to a value 
in that array ends up modifying the old memory used previously by 
that array. This seems counterintuitive to me in the sense that 
it feels logical that the lvalue to be assigned to should be 
evaluated after the function has been evaluated, but this 
behaviour implies that part of the lvalue was evaluated before 
the function.

A minimal reproduction of the issue I'm describing is attached 
below:

```
import std.exception;

void main() {
     auto v = new ulong[1];
     size_t appendAndGetLength() {
         v ~= [10, 10, 10, 10, 10, 10, 10, 10, 10, 10];
         return v.length;
     }
     v[0] = appendAndGetLength();
     // Works if we do the following instead
     // auto v0 = appendAndGetLength();
     // v[0] = v0;
     enforce(v[0] == v.length);
}
```

When running this code, it fails the enforcement because v[0] 
evaluates to 0 at the end, this ceases to be a problem if I 
introduce a temporary variable. I am confused as to why this is 
the case, and why adding the temporary fixed it. Can someone 
please help me determine why this is happening? It seems 
counterintuitive, and almost feels a bit like a footgun.

I tried looking in the spec for references to why this was 
happening, the closest I could find was a [footnote about 
undefined behaviour if aliased reference types are 
assigned](https://dlang.org/spec/expression.html#assign_expressions). I believe that this shouldn't apply in this case, because while the lvalue of the assignment is a reference to the array, the rvalue is a size_t (the result of evaluating the function).


More information about the Digitalmars-d mailing list