Bug 19917 – unions should require that all members are `= void` initialised

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-05-28T22:28:20Z
Last change time
2021-07-30T12:25:44Z
Keywords
pull
Assigned to
No Owner
Creator
Manu

Comments

Comment #0 by turkeyman — 2019-05-28T22:28:20Z
Unions should require that all members are `= void` initialised. Perhaps allow just one union member to omit the `= void` initialisation... but zero would also be fine. It's not possible that 2 or more members express initialisation intent, and it should be a compile error. struct S { union { int x; float y; // COMPILE ERROR, 'x' already initialised! } union { int z; float w = void; // <- this is fine } }
Comment #1 by iamthewilsonator — 2019-05-29T05:11:24Z
The way it currently works is the first member of a union is the one that dictates the .init of the union struct S { union { int x; float y; // COMPILE ERROR, 'x' already initialised! } union { int z; float w = void; // <- this is fine } } S s; assert( (cast(int*)&s)[0 .. 2]) == [0,0]); // passes reverse the order and the assert fails. If you want void initialisation then if know (or can compute) the size of the union (say N) then you can make the first member a `void[N] dummy;`. If the docs need to make that more explicit do say so, go forth and complain on the forums!
Comment #2 by turkeyman — 2019-05-29T07:46:30Z
Okay... well take this as the enhancement request that it is ;) That existing rule you describe is unintuitive and terrible. Users should specify `= void` on every member except one of their choosing. You can't possibly go wrong then, and there's also zero magic rules in the compiler that need to be explained under that arrangement.
Comment #3 by kinke — 2019-05-29T19:16:27Z
I've just seen that LDC handles this differently than DMD. With LDC, an explicit initializer takes precedence, regardless of the lexical order: union S { int x; // compiler error if also explicitly initialized (except for `= void`) float y = 1.0f; } void main() { S s; assert(s.y == 1.0f); }
Comment #4 by turkeyman — 2019-05-29T21:16:41Z
Wow. Seriously, the only sensible thing to do is issue a compile error if more than one item doesn't have `= void`. That would be very sane.
Comment #5 by kinke — 2019-05-29T21:23:34Z
Nah, I think LDC's way is fine, but it could be improved by *requiring* (exactly) one field to be explicitly initialized - clear as day and not much more syntax overhead: union U { int i; float f = 1.0f; real r; } vs. union U { int i = void; float f = 1.0f; real r = void; } and union U { int i = 0; float f; real r; } vs. union U { int i; float f = void; real r = void; }
Comment #6 by turkeyman — 2019-05-29T21:34:19Z
Either way. I like the `= void` personally. It's explicit, and there's no magic rules to implement in the compiler. It's also not always convenient to express a default construction.
Comment #7 by andrei — 2019-06-04T16:20:58Z
That's excessive. Pasting from https://issues.dlang.org/show_bug.cgi?id=19919: I think the principle of maximum simplicity goes like this: * Only the first field can have an initializer (if you want another field... move it to the top). * If that initializer is "= void", the union is void-initialized. All else is in error. That's that. Doesn't prevent any work getting done and is simple to spec and implement.
Comment #8 by turkeyman — 2019-06-04T17:35:23Z
(In reply to Andrei Alexandrescu from comment #7) > That's excessive. Pasting from > https://issues.dlang.org/show_bug.cgi?id=19919: > > I think the principle of maximum simplicity goes like this: > > * Only the first field can have an initializer (if you want another field... > move it to the top). > * If that initializer is "= void", the union is void-initialized. > > All else is in error. That's that. Doesn't prevent any work getting done and > is simple to spec and implement. I don't think it's simple, it's a weird magic rule that you wouldn't/couldn't expect, and you can't know unless you already know. Anyway, if it is the case, then the compiler needs to emit an error if an initialisation is applied to any non-first member explaining that rule.
Comment #9 by dlang-bot — 2019-06-26T09:46:45Z
@RazvanN7 created dlang/dmd pull request #10092 "Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void" fixing this issue: - Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void https://github.com/dlang/dmd/pull/10092
Comment #10 by dlang-bot — 2019-07-02T12:26:03Z
@RazvanN7 created dlang/dmd pull request #10122 "Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void" fixing this issue: - Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void https://github.com/dlang/dmd/pull/10122
Comment #11 by dlang-bot — 2019-07-10T16:45:22Z
dlang/dmd pull request #10122 "Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void" was merged into master: - a6c0a59757d137829187801fc059e4198c18e67d by RazvanN7: Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void - 523dfc1b1be6759ebca5139ec805946bcd29f7d0 by RazvanN7: Fix Issues 19919 and 19917 - Incorrect initialization of union when first member isn't marked = void https://github.com/dlang/dmd/pull/10122
Comment #12 by dlang-bot — 2021-07-30T12:25:44Z
dlang/dmd pull request #12899 "End deprecation period for incorrect initialization of union when first member isn't marked (Issues 19919 and 19917)" was merged into master: - 5600f50c129c45d7867238a0488fc49f8aa167cd by Iain Buclaw: End deprecation period for incorrect initialization of union when first member isn't marked (Issues 19919 and 19917) https://github.com/dlang/dmd/pull/12899