Bug 19903 – postblit called for uninitialised elements of unions

Status
RESOLVED
Resolution
DUPLICATE
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-05-26T17:14:34Z
Last change time
2019-05-28T12:08:22Z
Assigned to
No Owner
Creator
Manu

Comments

Comment #0 by turkeyman — 2019-05-26T17:14:34Z
import std.stdio; struct T { this(this) { writeln("dun postblit\n"); } float f = 0; } struct S { union { int x = 0; T y = void; // <- void initialised } int which = 0; } S a; S b = a; // <- assignment calls postblit This assignment calls the T postblit, which is a `void` initialised member of a union. This is just a hard crash waiting to happen! This pattern should be supplanted with copy-ctors. I suggest a reasonable resolution is: 1. no such implicit non-trivial assignment is attempted inside a union 2. if a union contains an element with a non-trivial copy, then a copy-ctor must be defined otherwise user receives a compile error informing them such. 2a. perhaps rather than emitting a compile error, it might be better to emit an automatic @disable copy constructor for that object. I think it's the case that any union with elaborate copy semantics can only be correctly composed by the author of the union.
Comment #1 by turkeyman — 2019-05-26T20:40:07Z
Oh my, I just noticed that the DESTRUCTOR is also called for each element in the union! That's completely wrong, since only one item in the union may be valid at a time.
Comment #2 by turkeyman — 2019-05-27T21:37:09Z
Raising this to blocker. unions are completely useless in D with this issue in place, and I can't continue.
Comment #3 by razvan.nitu1305 — 2019-05-28T11:17:57Z
(In reply to Manu from comment #0) > This assignment calls the T postblit, which is a `void` initialised member > of a union. > This is just a hard crash waiting to happen! > > This pattern should be supplanted with copy-ctors. > I suggest a reasonable resolution is: > 1. no such implicit non-trivial assignment is attempted inside a union > 2. if a union contains an element with a non-trivial copy, then a > copy-ctor must be defined otherwise user receives a compile error informing > them such. > 2a. perhaps rather than emitting a compile error, it might be better to > emit an automatic @disable copy constructor for that object. > > I think it's the case that any union with elaborate copy semantics can only > be correctly composed by the author of the union. Spec: "Unions may have fields that have postblits. However, a union itself never has a postblit. Copying a union does not result in postblit calls for any fields. If those calls are desired, they must be inserted explicitly by the programmer." It seems that it has a problem with anonymous unions. Slightly changing your program results in corect behavior: import std.stdio; struct T { this(this) { writeln("dun postblit\n"); } float f = 0; } struct S { union U { // the union is named now int x = 0; T y = void; // <- void initialised } U u; // and we have a field int which = 0; } S a; S b = a; // <- assignment calls postblit
Comment #4 by simen.kjaras — 2019-05-28T12:08:22Z
*** This issue has been marked as a duplicate of issue 19122 ***