www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "ubyte[size] store = void" in std.variant

reply Graham Fawcett <fawcett uwindsor.ca> writes:
Hi folks,

The following statement appears in std.variant:

190    union
191    {
192        ubyte[size] store = void;
193        // conservatively mark the region as pointers
194        static if (size >= (void*).sizeof)
195            void* p[size / (void*).sizeof];
196    }

The '= void' on line 192 sometimes leads to 'Error: void initializer
has no value' errors in application code. For example, this fails to
compile on DMD 2.047:

  foreach (int v; map! "a.get!int" (variantArray(1,2,3)))
    writeln(v);

Changing line 192 to 'ubyte[size] store;' resolves the issue.

My question is: what is the point of the '= void' initializer here?
Would std.variant be broken if '= void' were removed?

Thanks,
Graham
Jun 15 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 15 Jun 2010 09:04:23 -0400, Graham Fawcett <fawcett uwindsor.ca>  
wrote:

 Hi folks,

 The following statement appears in std.variant:

 190    union
 191    {
 192        ubyte[size] store = void;
 193        // conservatively mark the region as pointers
 194        static if (size >= (void*).sizeof)
 195            void* p[size / (void*).sizeof];
 196    }

 The '= void' on line 192 sometimes leads to 'Error: void initializer
 has no value' errors in application code. For example, this fails to
 compile on DMD 2.047:

   foreach (int v; map! "a.get!int" (variantArray(1,2,3)))
     writeln(v);

 Changing line 192 to 'ubyte[size] store;' resolves the issue.

 My question is: what is the point of the '= void' initializer here?
 Would std.variant be broken if '= void' were removed?

= void means don't initialize the data. Otherwise, the compiler/runtime will fill in the data will all 0s. However, I'm not sure how that works with a union, since you may have conflicting requirements for initialization. Is there a place in the spec that covers this? -Steve
Jun 15 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Graham Fawcett:
   struct foo {
     enum N = 10; // or whatever
     ubyte[N] store = void;
   }
   foo z = foo();

I think there's a bug there, you can add it to Bugzilla (if not already present): struct Foo { int[1] a = void; } void main() { Foo f = Foo(); } Bye, bearophile
Jun 15 2010
prev sibling next sibling parent Graham Fawcett <fawcett uwindsor.ca> writes:
On Tue, 15 Jun 2010 10:29:56 -0400, Steven Schveighoffer wrote:

 On Tue, 15 Jun 2010 09:04:23 -0400, Graham Fawcett <fawcett uwindsor.ca>
 wrote:
 
 Hi folks,

 The following statement appears in std.variant:

 190    union
 191    {
 192        ubyte[size] store = void;
 193        // conservatively mark the region as pointers 194       
 static if (size >= (void*).sizeof) 195            void* p[size /
 (void*).sizeof]; 196    }

 The '= void' on line 192 sometimes leads to 'Error: void initializer
 has no value' errors in application code. For example, this fails to
 compile on DMD 2.047:

   foreach (int v; map! "a.get!int" (variantArray(1,2,3)))
     writeln(v);

 Changing line 192 to 'ubyte[size] store;' resolves the issue.

 My question is: what is the point of the '= void' initializer here?
 Would std.variant be broken if '= void' were removed?

= void means don't initialize the data. Otherwise, the compiler/runtime will fill in the data will all 0s. However, I'm not sure how that works with a union, since you may have conflicting requirements for initialization.

I'm not sure if it's in the spec, but a quick test results in a compiler error if I declare a union with overlapping initializers. Simplifying the 'std.variant' case, I get the same 'void initializer has no value' error like this: struct foo { ubyte[] store = void; } foo z = foo(); Is this a compiler bug? Graham
Jun 15 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 15 Jun 2010 11:18:07 -0400, Graham Fawcett <fawcett uwindsor.ca>  
wrote:

 On Tue, 15 Jun 2010 10:29:56 -0400, Steven Schveighoffer wrote:

 On Tue, 15 Jun 2010 09:04:23 -0400, Graham Fawcett <fawcett uwindsor.ca>
 wrote:

 Hi folks,

 The following statement appears in std.variant:

 190    union
 191    {
 192        ubyte[size] store = void;
 193        // conservatively mark the region as pointers 194
 static if (size >= (void*).sizeof) 195            void* p[size /
 (void*).sizeof]; 196    }

 The '= void' on line 192 sometimes leads to 'Error: void initializer
 has no value' errors in application code. For example, this fails to
 compile on DMD 2.047:

   foreach (int v; map! "a.get!int" (variantArray(1,2,3)))
     writeln(v);

 Changing line 192 to 'ubyte[size] store;' resolves the issue.

 My question is: what is the point of the '= void' initializer here?
 Would std.variant be broken if '= void' were removed?

= void means don't initialize the data. Otherwise, the compiler/runtime will fill in the data will all 0s. However, I'm not sure how that works with a union, since you may have conflicting requirements for initialization.

I'm not sure if it's in the spec, but a quick test results in a compiler error if I declare a union with overlapping initializers. Simplifying the 'std.variant' case, I get the same 'void initializer has no value' error like this: struct foo { ubyte[] store = void; } foo z = foo(); Is this a compiler bug?

Note, you can only use = void on a value type, not a dynamic array. The variant union member is a static array, not a dynamic one. But actually, now that I think about it, =void is generally used in a function, not in a type definition. I'm not sure = void should be allowed in that context. So maybe the compiler is right to complain... -Steve
Jun 15 2010
prev sibling next sibling parent Graham Fawcett <fawcett uwindsor.ca> writes:
On Tue, 15 Jun 2010 11:24:48 -0400, Steven Schveighoffer wrote:

 On Tue, 15 Jun 2010 11:18:07 -0400, Graham Fawcett <fawcett uwindsor.ca>
 wrote:
 
 On Tue, 15 Jun 2010 10:29:56 -0400, Steven Schveighoffer wrote:

 On Tue, 15 Jun 2010 09:04:23 -0400, Graham Fawcett
 <fawcett uwindsor.ca> wrote:

 Hi folks,

 The following statement appears in std.variant:

 190    union
 191    {
 192        ubyte[size] store = void;
 193        // conservatively mark the region as pointers 194 static
 if (size >= (void*).sizeof) 195            void* p[size /
 (void*).sizeof]; 196    }

 The '= void' on line 192 sometimes leads to 'Error: void initializer
 has no value' errors in application code. For example, this fails to
 compile on DMD 2.047:

   foreach (int v; map! "a.get!int" (variantArray(1,2,3)))
     writeln(v);

 Changing line 192 to 'ubyte[size] store;' resolves the issue.

 My question is: what is the point of the '= void' initializer here?
 Would std.variant be broken if '= void' were removed?

= void means don't initialize the data. Otherwise, the compiler/runtime will fill in the data will all 0s. However, I'm not sure how that works with a union, since you may have conflicting requirements for initialization.

I'm not sure if it's in the spec, but a quick test results in a compiler error if I declare a union with overlapping initializers. Simplifying the 'std.variant' case, I get the same 'void initializer has no value' error like this: struct foo { ubyte[] store = void; } foo z = foo(); Is this a compiler bug?

Note, you can only use = void on a value type, not a dynamic array. The variant union member is a static array, not a dynamic one.

Oops, thanks for catching that. I was trying various combinations of types and array-sizes to look for a pattern. For the record, struct foo { enum N = 10; // or whatever ubyte[N] store = void; } foo z = foo(); ...returns the same error. Graham
 But actually, now that I think about it, =void is generally used in a
 function, not in a type definition.  I'm not sure = void should be
 allowed in that context.  So maybe the compiler is right to complain...
 
 -Steve

Jun 15 2010
prev sibling next sibling parent Graham Fawcett <fawcett uwindsor.ca> writes:
On Tue, 15 Jun 2010 13:24:07 -0400, bearophile wrote:

 Graham Fawcett:
   struct foo {
     enum N = 10; // or whatever
     ubyte[N] store = void;
   }
   foo z = foo();

I think there's a bug there, you can add it to Bugzilla (if not already present): struct Foo { int[1] a = void; } void main() { Foo f = Foo(); } Bye, bearophile

OK, added. http://d.puremagic.com/issues/show_bug.cgi?id=4322 "void initializer has no value" on struct/union members initialized to "void" Thanks, Graham
Jun 15 2010
prev sibling parent Graham Fawcett <fawcett uwindsor.ca> writes:
On Tue, 15 Jun 2010 17:39:50 +0000, Graham Fawcett wrote:

 On Tue, 15 Jun 2010 13:24:07 -0400, bearophile wrote:
 
 Graham Fawcett:
   struct foo {
     enum N = 10; // or whatever
     ubyte[N] store = void;
   }
   foo z = foo();

I think there's a bug there, you can add it to Bugzilla (if not already present): struct Foo { int[1] a = void; } void main() { Foo f = Foo(); } Bye, bearophile

OK, added. http://d.puremagic.com/issues/show_bug.cgi?id=4322 "void initializer has no value" on struct/union members initialized to "void" Thanks, Graham

FWIW, removing line 100 in init.c allows our simple examples to compile and run correctly. Of course I'm not 100% clear on why the error message was there in the first place. :) diff --git a/trunk/src/init.c b/trunk/src/init.c index ed3a091..cf9bc72 100644 --- a/trunk/src/init.c +++ b/trunk/src/init.c -97,7 +97,6 Initializer *VoidInitializer::semantic(Scope *sc, Type *t) Expression *VoidInitializer::toExpression() { - error(loc, "void initializer has no value"); return new IntegerExp(0); } best, Graham
Jun 15 2010