Comment #0 by bearophile_hugs — 2013-07-14T14:35:41Z
class Bar {
const int[1000] x = void;
this(int n) {
x[] = n;
}
}
void main() {}
dmd 2.064alpha gives errors but I think the code is correct:
test.d(2): Warning: const field with initializer should be static, __gshared, or an enum
test.d(4): Error: slice x[] is not mutable
There is also some discussion in this thread:
http://forum.dlang.org/thread/[email protected]
Comment #1 by maxim — 2013-07-14T19:38:14Z
From http://dlang.org/changelog.html#staticfields : "Eventually, they will be deprecated, and then will trigger an error."
The issue is that void initializer does not disable initialization but fills aggregate member with zero (it also fills data with zeros for types which .init property is not zero). If you replace void with some number, the code would not still compile, so this is not a specific to void. Also this fails in accordance with change-log.
I think this can be change to request to make void behavior to what it does for local variables or request to update the spec, but in current circumstances this issue is resolved-invalid.
Comment #2 by monarchdodra — 2013-12-14T07:01:10Z
(In reply to comment #1)
> The issue is that void initializer does not disable initialization but fills
> aggregate member with zero (it also fills data with zeros for types which .init
> property is not zero).
Technically, void initialization implies *no* initialization whatsoever:
//----
void main()
{
{
int i = 5;
}
int i = void;
assert(i == 5;
}
//----
When a *member* of a struct is declared void, it's value may be padded with anything the compiler wishes. Regardless of what the bits are, the value remains non-initialized.
> If you replace void with some number, the code would not
> still compile, so this is not a specific to void. Also this fails in accordance
> with change-log.
I don't understand this answer. "Non"-initialization is *still* initialization to T.init, yet that's allowed.
> From http://dlang.org/changelog.html#staticfields : "Eventually, they will be
> deprecated, and then will trigger an error."
I don't understand why it is not legal to have a const member with an initializer. So now it is impossible to do this?
struct S
{
const(int) i = 5; //default const value
this(int n)
{
i = n; //Override default
}
}
void main()
{
S s;
assert(s.i == 5);
}
Comment #3 by maxim — 2013-12-14T07:21:23Z
(In reply to comment #2)
> (In reply to comment #1)
> > The issue is that void initializer does not disable initialization but fills
> > aggregate member with zero (it also fills data with zeros for types which .init
> > property is not zero).
>
> Technically, void initialization implies *no* initialization whatsoever:
>
> //----
> void main()
> {
> {
> int i = 5;
> }
> int i = void;
> assert(i == 5;
> }
> //----
Actually there is difference between void initialization of variable and member field. In first case it is as you say, but in second case void initialization means filling data with zero bytes. You may argue that it is incorrect, but untill the behavior is changed, you are stuck with it.
Anyway, void is irrelevant to the issue, because judjing by issue 11739, you have something different in mind.
> When a *member* of a struct is declared void, it's value may be padded with
> anything the compiler wishes. Regardless of what the bits are, the value
> remains non-initialized.
>
> > If you replace void with some number, the code would not
> > still compile, so this is not a specific to void. Also this fails in accordance
> > with change-log.
>
> I don't understand this answer. "Non"-initialization is *still* initialization
> to T.init, yet that's allowed.
Yes, but this is third case. Why is it relevant here? I think you are just confuse the discussion.
> > From http://dlang.org/changelog.html#staticfields : "Eventually, they will be
> > deprecated, and then will trigger an error."
>
> I don't understand why it is not legal to have a const member with an
> initializer. So now it is impossible to do this?
>
> struct S
> {
> const(int) i = 5; //default const value
> this(int n)
> {
> i = n; //Override default
> }
> }
>
> void main()
> {
> S s;
> assert(s.i == 5);
> }
Ok, here is what you really mean (i think). Note, that the code fails with any initializer (void or some value), so void is irrelevant. Default initialization is also irrelevant because you have initializer. So, the issue of interest is:
struct S
{
const(int) i = void; // or any other initializer
this(int j)
{
i = j;
}
}
From changelog: Eventually, they will be deprecated, and then will trigger an error. Such fields should now be changed to enum or static. Making a field implicitly static based on whether it is const/immutable and has an initializer leads to confusion. The static keyword can be used to explicitly make any field static.
That is why the code is rejected. I would add into rationale additional point: having initializer and overwriting field is useless because you either know in beforehand value of a member (and use initializer), or you do not (and set value in RT).
Comment #4 by monarchdodra — 2013-12-14T09:05:49Z
(In reply to comment #3)
> Ok, here is what you really mean (i think). Note, that the code fails with any
> initializer (void or some value), so void is irrelevant. Default initialization
> is also irrelevant because you have initializer. So, the issue of interest is:
>
> struct S
> {
> const(int) i = void; // or any other initializer
> this(int j)
> {
> i = j;
> }
> }
>
> From changelog: Eventually, they will be deprecated, and then will trigger an
> error. Such fields should now be changed to enum or static. Making a field
> implicitly static based on whether it is const/immutable and has an initializer
> leads to confusion. The static keyword can be used to explicitly make any field
> static.
>
> That is why the code is rejected.
I understand the changelog, and why the code is rejected, but I disagree with the rationale:
The change is due to the fact that const members were static by default. We are changing this, however, to make sure people are correctly impacted, we are making the old semantic explicitly illegal.
*BUT*, if I want to declare an actual struct with a const field (eg: it can't be changed, but each struct has its own value). I'd want that field's default value to be "5", but for that value to *possibly* be chosen differently at declaration. I see no problem with doing this.
However, it seems that even though we have deprecated the "semantic", we still have the wrong behavior:
> I would add into rationale additional point:
> having initializer and overwriting field is useless because you either know in
> beforehand value of a member (and use initializer), or you do not (and set
> value in RT).
Or... you want to have a default value (5) which is implementation defined, which the user may or may not decide to not use:
//----
struct S
{
const(int) i = 5;
}
void main()
{
S s1; //*Should* be 5
S s2 = S(6); //*Should* be 6 (doesn't work)
}
//----
If we'd just change right now (still hasn't been done) so that non-statics are actually... non-static, we wouldn't have this problem.
Comment #5 by jakobovrum — 2013-12-14T11:06:09Z
*** Issue 11741 has been marked as a duplicate of this issue. ***
Comment #6 by k.hara.pg — 2013-12-14T11:12:44Z
(In reply to comment #0)
> class Bar {
> const int[1000] x = void;
> this(int n) {
> x[] = n;
> }
> }
> void main() {}
http://dlang.org/changelog.html#staticfields
In 2.063, just only warning was added for implicitly static aggregate members.
So currently, Bar.x is still made static implicitly.
And, you cannot initialize static variable inside instance constructor. Therefore, essentially current behavior is not a bug.
...But, fortunately(?), void initialized variable is currently not initializable inside static constructor.
class Bar {
const int x = void;
static this() { x = 1; } // NG!
}
const int x = void;
static this() { x = 10; } // NG!
This is another compiler bug (I filed it in bug 11742). But for the reason we can fix this issue without breaking any existing code.
Comment #7 by k.hara.pg — 2013-12-14T11:14:53Z
*** Issue 11739 has been marked as a duplicate of this issue. ***