burner / bugzilla_migration_test

0 stars 0 forks source link

Bogus "overlapping initialization" error with structs, unions, and member initializers #17

Open burner opened 17 years ago

burner commented 17 years ago

jarrett.billingsley reported this on 2007-08-19T09:58:36Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=1432

CC List

Description

struct S { int blah = 5;

union
{
    int x;
    T t;
    Object o;
}

}

struct T { int y; }

Gives the error "dtest.d(26): struct dtest.S overlapping initialization for struct S.blah"

If you remove the initializer for S.blah, or if you remove the t member from that union, or if you make the union named, it works.

burner commented 15 years ago

tomas commented on 2009-04-22T21:33:19Z

Another variation:

union S { float[2] a; struct { union { float i = 1; float x; } union { float j = 2; float y; } } }

$ dmd bar.d -c bar.d(2): Error: union bar.S overlapping initialization for struct S.i bar.d(2): Error: union bar.S overlapping initialization for struct S.j

If 'a' is moved below the anonymous struct it works. The spec does not mention this special case as far as I can tell. Explicit initialization of aggregate fields inside anonymous struct/union combinations should be documented.

burner commented 12 years ago

hoganmeier commented on 2011-11-27T06:08:55Z

The first example compiles fine now. Really not sure if the second should compile at all, but the order of compilation dependence is definitely a bug.

burner commented 10 years ago

k.hara.pg commented on 2013-10-01T07:16:17Z

(In reply to comment #1)

Another variation:

union S { float[2] a; struct { union { float i = 1; float x; } union { float j = 2; float y; } } }

$ dmd bar.d -c bar.d(2): Error: union bar.S overlapping initialization for struct S.i bar.d(2): Error: union bar.S overlapping initialization for struct S.j

If 'a' is moved below the anonymous struct it works. The spec does not mention this special case as far as I can tell. Explicit initialization of aggregate fields inside anonymous struct/union combinations should be documented.

More reduced test case.

union U1 { int a = 1; // OK string b; } union U2 { int a; string b = "s"; // overlapping initialization for struct U2.b }

I discovered this behavior while debugging other compiler bug. If there's overlapped fields, and the non-first field is explicitly initialized, compiler rejects it by "overlapping initialization".

As far as I see, the behavior seems to be intended by the current compiler code. However, normally D language semantics does not rely on the lexical order of declarations. I can agree that the behavior is contrary to the basic principle.


I'd propose more better semantics:

If exactly one field has an explicit initializer between overlapped fields, compiler should prefer it for default initialization.

U1 u1; assert(u1.a == 1); U2 u2; assert(u2.b == "s");

If there's no explicitly initialized field between overlapped siblings, the first one is initialized at the default initialization.

union U3 { int a; char c; } U3 u3; assert(u3.a == 0); union U4 { char c; int a; } U4 u4; assert(u4.c == 0xff);

If two or more fields have explicit initializers between overlapped siblings, it would cause compilation error.

union U5 { int a = 1, string b = "s" } U5 u5; // Error: overlapped initialization between U5.a and U5.b

How about that?

burner commented 10 years ago

k.hara.pg commented on 2013-10-01T07:17:08Z

Change to D2 issue.

burner commented 10 years ago

code (@MartinNowak) commented on 2013-12-16T00:10:49Z

Do we have a distinction between explicit and implicit initialization somewhere else in the language? Otherwise it's idfficult to explain, why these two differ. union { int a; string b = "s"; } union { int a = 0; string b = "s"; }

burner commented 10 years ago

k.hara.pg commented on 2013-12-16T00:51:07Z

(In reply to comment #5)

Do we have a distinction between explicit and implicit initialization somewhere else in the language? Otherwise it's idfficult to explain, why these two differ. union { int a; string b = "s"; } union { int a = 0; string b = "s"; }

I think the main argument of this issue is, that explicitly initialized overlapped field should be always preferred than default initializing.

The two concepts, overlapping fields and default initializing behavior for safely programming is normally conflict each other, because Compiler cannot initialize all of overlapped fields by default. Therefore, D language should specially treat overlapped fields.

For union U { T1 f1; T2 f2; ... }, T1.init is picked for the default initializer of overlapped fields. I think it is legitimate behavior because it is C-compatible.

However, if only one overlapped fields are explicitly initialized by programmer, current dmd behaves foolish.

union U1 { T1 f1 = x; T2 f2; } // x is used for default initializer

union U2 { T1 f1; T2 f2 = x; } // x conflicts with implicitly picked default initializer T1.init !

This is D-specific case, and I think the current behavior is contrary to the two D language concepts -

  1. If programmer specifies something explicitly, compiler should respect it.
  2. If it is unnecessary, order dependent feature is not good.

In the U2 case, programmer explicitly add a initializer for the overlapped field f2. So, I think compiler should pick it.

Of course, two or more overlapped fields have explicit initializers, it should be an error.

union U3 { T1 f1 = x; T2 f2 = y; // explicit specified initializers x and y conflicts each other

burner commented 10 years ago

code (@MartinNowak) commented on 2013-12-16T12:52:04Z

I see, you're right. Specifically one should be able to explicitly default initialize a field. union { T1 t1; T2 t2 = T2.init; }

NB: A workaround to the aforementioned bug is to simply change the order of union fields so that the one with explicit initializer comes first.

burner commented 7 years ago

simen.kjaras commented on 2017-09-19T09:54:10Z

This works in 2.075.1.

burner commented 2 years ago

ibuclaw (@ibuclaw) commented on 2021-12-26T22:52:18Z

This issue seems to be closed for the wrong reason.

From runnable/structlit.d:

union U7727A3 { int i; double d = 2.5; }

union U7727B3 { double d; int i = 123; }

void test7727() { import core.stdc.math : isnan;

// Blocked by https://issues.dlang.org/show_bug.cgi?id=1432 { U7727A3 u; assert(u.d == 2.5); } { U7727A3 u = { i: 1024 }; assert(u.i == 1024); } { U7727A3 u = { d: 1.225 }; assert(u.d == 1.225); } static assert(!__traits(compiles, { U7727A3 u = { i: 1024, d: 1.225 }; } ));

// Blocked by https://issues.dlang.org/show_bug.cgi?id=1432 { U7727B3 u; assert(u.i == 123); } { U7727B3 u = { i: 1024 }; assert(u.i == 1024); } { U7727B3 u = { d: 1.225 }; assert(u.d == 1.225); } static assert(!__traits(compiles, { U7727B3 u = { i: 1024, d: 1.225 }; } )); }