Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 03, 2013 We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
DMD has always accepted this initializer syntax for static arrays: float [50] x = 1.0; If this declaration happens inside a function, or in global scope, the compiler sets all members of x to 1.0. That is, it's the same as: float [50] x = void; x[] = 1.0; In my DMD pull requests, I've called this 'block initialization', since there was no standard name for it. A lot of code relies on this behaviour, but the spec doesn't mention it!!! The problem is not simply that this is unspecified. A long time ago, if this same declaration was a member of a struct declaration, the behaviour was completely different. It used to set x[0] to 1.0, and leave the others at float.init. I'll call this "first-element-initialization", and it still applies in many cases, for example when you use a struct static initializer. Ie, it's the same as: float [50] x; x[0] = 1.0; Note however that this part of the compiler has historically been very bug-prone, and the behaviour has changed several times. I didn't know about first-element-initialization when I originally did the CTFE code, so when CTFE is involved, it always does block initialization instead. Internally, the compiler has two functions, defaultInit() and defaultInitLiteral(). The first does first-element-init, the second does block-init. There are several other situations which do block initialization (not just CTFE). There are a greater number of situations where first-init can happen, but the most frequently encountered situations use block-init. There are even some foul cases, like bug 10198, where due to a bug in CTFE, you currently get a bizarre mix of both first-init and block-init! So, we have a curious mix of the two behaviours. Which way is correct? Personally I'd like to just use block-init everywhere. I personally find first-element-init rather unexpected, but maybe that's just me. I don't know when it would be useful. But regardless, we need to get this sorted out. It's a blocker for my CTFE work. Here's an example of some of the oddities: ---- struct S { int [3] x; } struct T { int [3] x = 8; } struct U { int [3][3] y; } void main() { int [3][4] w = 7; assert( w[2][2] == 7); // Passes, it was block-initialized S s = { 8 }; // OK, struct static initializer. first-element-init S r = S( 8 ); // OK, struct literal, block-init. T t; // Default initialized, block-init assert( s.x[2] == 8); // Fails; it was first-element-initialized assert( r.x[2] == 8); // Passes; all elements are 8. Block-init. assert( t.x[2] == 8); // Passes; all elements are 8. Block-init. U u = { 9 }; // Does not compile // Error: cannot implicitly convert expression (9) of type int to int[3LU][3LU] } --- |
June 03, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On Monday, 3 June 2013 at 09:06:25 UTC, Don wrote:
> Personally I'd like to just use block-init everywhere. I personally find first-element-init rather unexpected, but maybe that's just me. I don't know when it would be useful.
+1
I see no point in just initialising the first member. If you want that, just default init then set the first member.
|
June 03, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On 6/3/13, Don <turnyourkidsintocash@nospam.com> wrote: > A lot of code relies on this behaviour, but the spec doesn't mention it!!! I didn't know about it until Walter mentioned the syntax to me. I've found it quite useful since then. E.g.: char[100] buffer = 0; Without this buffer is normally initialized with 0xFF, and this could break C functions when you pass a pointer to such an array. > Personally I'd like to just use block-init everywhere. Me too. You get my vote. |
June 03, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On 2013-06-03, 11:06, Don wrote: > Personally I'd like to just use block-init everywhere. I personally find first-element-init rather unexpected, but maybe that's just me. I don't know when it would be useful. But regardless, we need to get this sorted out. > It's a blocker for my CTFE work. Votes++; -- Simen |
June 03, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On 06/03/2013 11:06 AM, Don wrote:
>
> Personally I'd like to just use block-init everywhere. I personally find
> first-element-init rather unexpected, but maybe that's just me. I don't
> know when it would be useful. But regardless, we need to get this sorted
> out.
> It's a blocker for my CTFE work.
Agreed, kill first-element init.
|
June 03, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Monday, 3 June 2013 at 19:41:35 UTC, Timon Gehr wrote: > On 06/03/2013 11:06 AM, Don wrote: >> >> Personally I'd like to just use block-init everywhere. […] > > Agreed, kill first-element init. Kill it with a vengeance! Honestly, I can't see how that could have ever been intended as a feature, and while fixing an issue in LDC a while back, I already removed that one instance with a first-element struct initializer from the test suite: https://github.com/ldc-developers/dmd-testsuite/blob/ldc/runnable/test42.d#L3226 David |
June 04, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On Monday, June 03, 2013 11:06:22 Don wrote:
> So, we have a curious mix of the two behaviours. Which way is correct?
>
> Personally I'd like to just use block-init everywhere. I
> personally find first-element-init rather unexpected, but maybe
> that's just me. I don't know when it would be useful. But
> regardless, we need to get this sorted out.
> It's a blocker for my CTFE work.
I honestly didn't know about either, but first element init seems very wrong to me, whereas block init makes sense.
- Jonathan M Davis
|
June 04, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On Monday, 3 June 2013 at 09:06:25 UTC, Don wrote:
> Personally I'd like to just use block-init everywhere. I personally find first-element-init rather unexpected, but maybe that's just me. I don't know when it would be useful. But regardless, we need to get this sorted out.
> It's a blocker for my CTFE work.
>
KILL IT WITH FIRE !
|
June 04, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On Mon, 03 Jun 2013 05:06:22 -0400, Don <turnyourkidsintocash@nospam.com> wrote: > DMD has always accepted this initializer syntax [with unexplained black magic behavior that is inconsistent from one usage to the next] BURRRRRN IT!!!! Seriously, I had no idea this was going on. It would surprise the hell out of me if I had discovered it! -Steve |
June 04, 2013 Re: We need to define the semantics of block initialization of arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Attachments:
| 2013/6/3 Don <turnyourkidsintocash@nospam.com> > DMD has always accepted this initializer syntax for static arrays: > > float [50] x = 1.0; > > If this declaration happens inside a function, or in global scope, the compiler sets all members of x to 1.0. That is, it's the same as: > > float [50] x = void; > x[] = 1.0; > > In my DMD pull requests, I've called this 'block initialization', since there was no standard name for it. > > A lot of code relies on this behaviour, but the spec doesn't mention it!!! > > The problem is not simply that this is unspecified. A long time ago, if this same declaration was a member of a struct declaration, the behaviour was completely different. It used to set x[0] to 1.0, and leave the others at float.init. I'll call this "first-element-initialization"**, and it still applies in many cases, for example when you use a struct static initializer. Ie, it's the same as: > > float [50] x; > x[0] = 1.0; > > Note however that this part of the compiler has historically been very bug-prone, and the behaviour has changed several times. > > > I didn't know about first-element-initialization when I originally did the > CTFE code, so when CTFE is involved, it always does block initialization > instead. > Internally, the compiler has two functions, defaultInit() and > defaultInitLiteral(). The first does first-element-init, the second does > block-init. > There are several other situations which do block initialization (not just > CTFE). There are a greater number of situations where first-init can > happen, but the most frequently encountered situations use block-init. > There are even some foul cases, like bug 10198, where due to a bug in CTFE, > you currently get a bizarre mix of both first-init and block-init! > > > So, we have a curious mix of the two behaviours. Which way is correct? > > Personally I'd like to just use block-init everywhere. I personally find > first-element-init rather unexpected, but maybe that's just me. I don't > know when it would be useful. But regardless, we need to get this sorted > out. > It's a blocker for my CTFE work. > First-element-init is definitely a bug. I can argue that nobody wants the strange behavior. Here's an example of some of the oddities: > ---- > struct S { > int [3] x; > } > > struct T { > int [3] x = 8; > } > > struct U { > int [3][3] y; > } > > void main() > { > int [3][4] w = 7; > assert( w[2][2] == 7); // Passes, it was block-initialized > Currently block-initialization for multi-dimensional static array is just only allowed for variable declaration in statement scope. I'm planning to fix bug 3849 and 7019, but changing this behavior might affect them. As my hope, I'd like to keep this as-is so I've not finished thinking about it well. S s = { 8 }; // OK, struct static initializer. first-element-init > This is definitely a bug. Instead, block-init should occur. > S r = S( 8 ); // OK, struct literal, block-init. > T t; // Default initialized, block-init > OK. > assert( s.x[2] == 8); // Fails; it was first-element-initialized > Also, definitely a bug. > assert( r.x[2] == 8); // Passes; all elements are 8. Block-init. > assert( t.x[2] == 8); // Passes; all elements are 8. Block-init. > OK. > U u = { 9 }; // Does not compile > // Error: cannot implicitly convert expression (9) of type int to > int[3LU][3LU] > For reasons I've already mentioned in `int [3][4] w = 7;`, I'd like to keep this current behavior. > } > --- > Kenji Hara |
Copyright © 1999-2021 by the D Language Foundation