We need to define the semantics of block initialization of arrays

Kenji Hara k.hara.pg at gmail.com
Mon Jun 3 19:33:40 PDT 2013


2013/6/3 Don <turnyourkidsintocash at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20130604/ea7c51d3/attachment.html>


More information about the Digitalmars-d mailing list