Thread overview
static if - unexpected results
Jun 23, 2023
DLearner
Jun 23, 2023
FeepingCreature
Jun 23, 2023
DLearner
Jun 23, 2023
H. S. Teoh
Jun 23, 2023
DLearner
Jun 24, 2023
FeepingCreature
Jun 23, 2023
Ali Çehreli
Jun 23, 2023
DLearner
June 23, 2023

Hi

Was looking for compile-time detection of a struct variable.
However, the following test code gave the two 'FAILS' shown below.
Comments?

void main() {
   import std.stdio : writeln;
   import std.traits;

   string mxnTst(string VarName) {
      return

      `static if (is(typeof(` ~ VarName ~ `) == char)) {` ~
         `writeln("` ~ VarName ~ ` ", " is a char");` ~
      `} else static if (__traits(isPOD, typeof(` ~ VarName ~ `))) {` ~
         `writeln("` ~ VarName ~ ` ", " is a struct");` ~
      `} else static if (is(typeof(` ~ VarName ~ `) == int)) {` ~
         `writeln("` ~ VarName ~ ` ", " is an int");` ~
      `} else {` ~
         `static assert(false, "mxnTst Variable '` ~ VarName  ~ `' is of unknown type");` ~
      `}`
       ;
   }

   char char1;
   int  int1;
   byte byte1;

   struct foo {
      int  fooint;
      char foochar;
   }
   foo foovar1;

   mixin(mxnTst("char1"));   // Expected: char1 is a char. Actual: char1 is a char. (ok)
   mixin(mxnTst("int1"));    // Expected: int1 is an int.  Actual: int1 is a struct. (FAIL)
   mixin(mxnTst("foovar1")); // Expected: foovar1 is a struct.  Actual: foovar1 is a struct. (ok)
   mixin(mxnTst("byte1"));   // Expected: Run to fail with the static assert message. Actual: byte1 is a struct. (FAIL)
}
June 23, 2023

On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote:

>

Hi

Was looking for compile-time detection of a struct variable.
However, the following test code gave the two 'FAILS' shown below.
Comments?

void main() {
   import std.stdio : writeln;
   import std.traits;

   string mxnTst(string VarName) {
      return

      `static if (is(typeof(` ~ VarName ~ `) == char)) {` ~
         `writeln("` ~ VarName ~ ` ", " is a char");` ~
      `} else static if (__traits(isPOD, typeof(` ~ VarName ~ `))) {` ~
         `writeln("` ~ VarName ~ ` ", " is a struct");` ~
      `} else static if (is(typeof(` ~ VarName ~ `) == int)) {` ~
         `writeln("` ~ VarName ~ ` ", " is an int");` ~
      `} else {` ~
         `static assert(false, "mxnTst Variable '` ~ VarName  ~ `' is of unknown type");` ~
      `}`
       ;
   }

   char char1;
   int  int1;
   byte byte1;

   struct foo {
      int  fooint;
      char foochar;
   }
   foo foovar1;

   mixin(mxnTst("char1"));   // Expected: char1 is a char. Actual: char1 is a char. (ok)
   mixin(mxnTst("int1"));    // Expected: int1 is an int.  Actual: int1 is a struct. (FAIL)
   mixin(mxnTst("foovar1")); // Expected: foovar1 is a struct.  Actual: foovar1 is a struct. (ok)
   mixin(mxnTst("byte1"));   // Expected: Run to fail with the static assert message. Actual: byte1 is a struct. (FAIL)
}
static assert(__traits(isPOD, int)); // ok.
static assert(__traits(isPOD, byte)); // ok.

It's a bug in either the spec or the compiler.

June 23, 2023

On Friday, 23 June 2023 at 14:31:45 UTC, FeepingCreature wrote:

>

On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote:
[...]

static assert(__traits(isPOD, int)); // ok.
static assert(__traits(isPOD, byte)); // ok.

It's a bug in either the spec or the compiler.

I am using

DMD64 D Compiler v2.103.0-dirty

under

Windows [Version 10.0.19045.3086]

Do I need to report this anywhere?

June 23, 2023

On Friday, 23 June 2023 at 15:22:36 UTC, DLearner wrote:

>

On Friday, 23 June 2023 at 14:31:45 UTC, FeepingCreature wrote:

>

On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote:
[...]

static assert(__traits(isPOD, int)); // ok.
static assert(__traits(isPOD, byte)); // ok.

It's a bug in either the spec or the compiler.

I am using

DMD64 D Compiler v2.103.0-dirty

under

Windows [Version 10.0.19045.3086]

Do I need to report this anywhere?

Tested your original code on latest dmd git master, here's the output:

char1  is a char
int1  is a struct
foovar1  is a struct
byte1  is a struct

Looks like there isn't a problem? Or at least, it's now fixed in git master.

Which exact version of dmd are you using? Did you download from dlang.org or did you build your own?

--T

June 23, 2023

On Friday, 23 June 2023 at 15:48:44 UTC, H. S. Teoh wrote:

>

On Friday, 23 June 2023 at 15:22:36 UTC, DLearner wrote:

>

On Friday, 23 June 2023 at 14:31:45 UTC, FeepingCreature wrote:

>

On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote:
[...]

static assert(__traits(isPOD, int)); // ok.
static assert(__traits(isPOD, byte)); // ok.

It's a bug in either the spec or the compiler.

I am using

DMD64 D Compiler v2.103.0-dirty

under

Windows [Version 10.0.19045.3086]

Do I need to report this anywhere?

Tested your original code on latest dmd git master, here's the output:

char1  is a char
int1  is a struct
foovar1  is a struct
byte1  is a struct

Looks like there isn't a problem? Or at least, it's now fixed in git master.

Which exact version of dmd are you using? Did you download from dlang.org or did you build your own?

--T

Probably I misunderstand, but to me:

int1  is a struct

and

byte1  is a struct

are both errors.

The 'struct' test is being triggered for things that are not structs.

June 23, 2023
On 6/23/23 07:22, DLearner wrote:

>        `} else static if (__traits(isPOD, typeof(` ~ VarName ~ `))) {` ~

Regardless, you can also use the 'is' expression with the 'struct' keyword. If T is a struct,

  is (T == struct)

that will produce true at compile time.

Ali

June 23, 2023
On Friday, 23 June 2023 at 16:51:16 UTC, Ali Çehreli wrote:
> On 6/23/23 07:22, DLearner wrote:
>
> >        `} else static if (__traits(isPOD, typeof(` ~ VarName
> ~ `))) {` ~
>
> Regardless, you can also use the 'is' expression with the 'struct' keyword. If T is a struct,
>
>   is (T == struct)
>
> that will produce true at compile time.
>
> Ali

Thanks for this - I can confirm it works.
June 23, 2023

On 6/23/23 10:31 AM, FeepingCreature wrote:

>

On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote:

>

Hi

Was looking for compile-time detection of a struct variable.
However, the following test code gave the two 'FAILS' shown below.
Comments?

void main() {
   import std.stdio : writeln;
   import std.traits;

   string mxnTst(string VarName) {
      return

      `static if (is(typeof(` ~ VarName ~ `) == char)) {` ~
         `writeln("` ~ VarName ~ ` ", " is a char");` ~
      `} else static if (__traits(isPOD, typeof(` ~ VarName ~ `))) {` ~
         `writeln("` ~ VarName ~ ` ", " is a struct");` ~
      `} else static if (is(typeof(` ~ VarName ~ `) == int)) {` ~
         `writeln("` ~ VarName ~ ` ", " is an int");` ~
      `} else {` ~
         `static assert(false, "mxnTst Variable '` ~ VarName  ~ `' is of unknown type");` ~
      `}`
       ;
   }

   char char1;
   int  int1;
   byte byte1;

   struct foo {
      int  fooint;
      char foochar;
   }
   foo foovar1;

   mixin(mxnTst("char1"));   // Expected: char1 is a char. Actual: char1 is a char. (ok)
   mixin(mxnTst("int1"));    // Expected: int1 is an int. Actual: int1 is a struct. (FAIL)
   mixin(mxnTst("foovar1")); // Expected: foovar1 is a struct. Actual: foovar1 is a struct. (ok)
   mixin(mxnTst("byte1"));   // Expected: Run to fail with the static assert message. Actual: byte1 is a struct. (FAIL)
}
static assert(__traits(isPOD, int)); // ok.
static assert(__traits(isPOD, byte)); // ok.

It's a bug in either the spec or the compiler.

It should be a spec change. Change POD to say "type" instead of "struct".

The goal of isPOD is to determine how careful generic code needs to be to pass the type around, or copy it. Changing it to false implies that it is not "plain old data". I.e. it has a destructor, it has hidden members, or it cannot be copied via bit copying (all of these do not fit the type in question).

The only other option is to error on calling __traits(isPOD, char), but I think that's even worse.

-Steve

June 24, 2023

On Friday, 23 June 2023 at 18:43:06 UTC, Steven Schveighoffer wrote:

>

It should be a spec change. Change POD to say "type" instead of "struct".

The goal of isPOD is to determine how careful generic code needs to be to pass the type around, or copy it. Changing it to false implies that it is not "plain old data". I.e. it has a destructor, it has hidden members, or it cannot be copied via bit copying (all of these do not fit the type in question).

The only other option is to error on calling __traits(isPOD, char), but I think that's even worse.

-Steve

Yeah, I think that's also where I'm standing. The current behavior seems correct and useful, it's just not documented correctly.