April 12, 2019
On Friday, 12 April 2019 at 09:43:01 UTC, Jacob Carlborg wrote:
> On 2019-04-11 20:13, Alex wrote:
>> The following code works when I comment out the static if
>> 
>> //static if (__traits(compiles, __traits(getAttributes, T)))
>>     static foreach(a;  __traits(getAttributes, T)) Attributes ~=
>> 
>> 
>> There seems to be absolutely no reason why this code would fail with the static if but pass without it but in the first case I get no attributes because the __traits compiles fails.
>> 
>> 
>> 
>> __traits(compiles, __traits(getAttributes, T))
>> 
>> vs
>> 
>> __traits(getAttributes, T)
>> 
>> How could it not compile in the first case and yet work in the foreach?
>
> The problem is that "__traits(getAttributes, T)" in it self is not valid code. It needs to be part of larger expression or statement. The following seems to work:
>
> https://run.dlang.io/is/JWkdbQ


So this suggests that the error is due to an expression, I thought compiles could take expressions ;/

onlineapp.d(17): Error: tuple(3) has no effect
3-int

@(3) int a;
__traits(getAttributes, a);

I use the same semantics all over the place and it seems to work:

static if (__traits(compiles, __traits(isTemplate, T)))


The same issue will happen, but I believe static if works here without issue. If so this means that it is a bug. Maybe compiles can have handle certain primitives(such as bools here) but not others(such as tuples in the main case)?

It would make little sense to be forced to use a temp variable:

static if (__traits(compiles, auto x = __traits(isTemplate, T)))

(after all, a ; is not required either)


In fact, though:

Returns a bool true if all of the arguments compile (are semantically correct). The arguments can be symbols, types, or expressions that are syntactically correct. The arguments cannot be statements or declarations.

If there are no arguments, the result is false.

import std.stdio;

struct S
{
    static int s1;
    int s2;
}

int foo();
int bar();

void main()
{
    writeln(__traits(compiles));                      // false
    writeln(__traits(compiles, foo));                 // true
    writeln(__traits(compiles, foo + 1));             // true
    writeln(__traits(compiles, &foo + 1));            // false
    writeln(__traits(compiles, typeof(1)));           // true
    writeln(__traits(compiles, S.s1));                // true
    writeln(__traits(compiles, S.s3));                // false
    writeln(__traits(compiles, 1,2,3,int,long,std));  // true
    writeln(__traits(compiles, 3[1]));                // false
    writeln(__traits(compiles, 1,2,3,int,long,3[1])); // false


So ultimately it suggests a bug in the compiler.









April 12, 2019
On 4/12/19 5:43 AM, Jacob Carlborg wrote:

> The problem is that "__traits(getAttributes, T)" in it self is not valid code. It needs to be part of larger expression or statement.

It does work, as long as it's not an alias passed into a template:

void main()
{
   @(3) int a;
   static assert(__traits(compiles, __traits(getAttributes, a))); // OK
   alias b = a;
   static assert(__traits(compiles, __traits(getAttributes, b))); // OK
   static void foo(alias c)() {
      static assert(__traits(compiles, __traits(getAttributes, c))); // Error
   }
   foo!a();
}

It seems like a straight-up bug to me. I don't see the difference between those 3 calls.

-Steve
1 2
Next ›   Last »