At least there's a dmd bug.

For such static array assignment, dmd should use druntime function, but instead plain memory copy operation used.
https://github.com/D-Programming-Language/dmd/blob/master/src/e2ir.c#L2920
https://github.com/D-Programming-Language/dmd/blob/master/src/e2ir.c#L2945

And, even after the bug is fixed, I think it's debatable behavior whether an element-wise assignment should call opAssign on each elements, because it can be a kind of optimization.

Related issue: https://issues.dlang.org/show_bug.cgi?id=8931

Kenji Hara


2015-07-20 23:18 GMT+09:00 David Nadlinger via Digitalmars-d <digitalmars-d@puremagic.com>:
Hi all,

I was about to fix an issue with postblits/destructors in LDC when I stumbled upon the following vexing behaviour in DMD (both 2.067.1 and master):

---
uint dtorCount;

struct S {
    uint x;
    void opAssign(const ref S rhs) { assert(false, "Not called"); }
    ~this() { ++dtorCount; }
}


void main() {
    S[2] a;
    a[0].x = 42;

    a = a.init;

    assert(a[0].x == 0); // as expected the value has been reset
    assert(dtorCount == 0); // Passes?!?
}
---

I would have expected this to either call opAssign or to destruct the instance, blit the init value, and call any postblits. However, as you can see neither the dtor nor opAssign are executed. If I add a postblit to S, then suddenly the dtor is invoked too.

Am I missing something here, or is this a major bug in struct lifetime handling?

I understand why this happens from the DMD source, but it almost seems like it was deliberately written this way; thus the question.

 — David