Thread overview
allMembers and getMember traits behavior
Jun 21, 2013
Martin
Jun 21, 2013
Jacob Carlborg
Jun 21, 2013
Martin
Jun 21, 2013
Artur Skawina
Jun 21, 2013
Martin
Jun 21, 2013
Jacob Carlborg
Jun 21, 2013
Artur Skawina
June 21, 2013
module test;

void test()
{


    foreach (member; __traits(allMembers, Client))
    {
        pragma(msg, member); // Prints all members fine, including "value"
    }

    // This line fails
    static if(__traits(getProtection, __traits(getMember, TestClass, "value")) == "public")
    {
        pragma(msg, "value is public");
    }
    else
    {
        pragma(msg, "value is not public");
    }

}

module testclass;

class TestClass
{
private:
    int value;
}

When using the allMembers trait, the private "value" member of TestClass is included, but when trying to retrieve that member using the getMember trait, it fails to compile with test.d(13): Error: class main.TestClass member value is not accessible

Is that intended behavior or a bug? I can't see why the getMember trait should not be able to retrieve private members when allMembers trait is
June 21, 2013
On 2013-06-21 15:04, Martin wrote:
> module test;
>
> void test()
> {
>
>
>      foreach (member; __traits(allMembers, Client))
>      {
>          pragma(msg, member); // Prints all members fine, including "value"
>      }
>
>      // This line fails
>      static if(__traits(getProtection, __traits(getMember, TestClass,
> "value")) == "public")
>      {
>          pragma(msg, "value is public");
>      }
>      else
>      {
>          pragma(msg, "value is not public");
>      }
>
> }
>
> module testclass;
>
> class TestClass
> {
> private:
>      int value;
> }
>
> When using the allMembers trait, the private "value" member of TestClass
> is included, but when trying to retrieve that member using the getMember
> trait, it fails to compile with test.d(13): Error: class main.TestClass
> member value is not accessible
>
> Is that intended behavior or a bug? I can't see why the getMember trait
> should not be able to retrieve private members when allMembers trait is

Can you use a string instead of getMember?

-- 
/Jacob Carlborg
June 21, 2013
On Friday, 21 June 2013 at 13:15:43 UTC, Jacob Carlborg wrote:
> On 2013-06-21 15:04, Martin wrote:
>> module test;
>>
>> void test()
>> {
>>
>>
>>     foreach (member; __traits(allMembers, Client))
>>     {
>>         pragma(msg, member); // Prints all members fine, including "value"
>>     }
>>
>>     // This line fails
>>     static if(__traits(getProtection, __traits(getMember, TestClass,
>> "value")) == "public")
>>     {
>>         pragma(msg, "value is public");
>>     }
>>     else
>>     {
>>         pragma(msg, "value is not public");
>>     }
>>
>> }
>>
>> module testclass;
>>
>> class TestClass
>> {
>> private:
>>     int value;
>> }
>>
>> When using the allMembers trait, the private "value" member of TestClass
>> is included, but when trying to retrieve that member using the getMember
>> trait, it fails to compile with test.d(13): Error: class main.TestClass
>> member value is not accessible
>>
>> Is that intended behavior or a bug? I can't see why the getMember trait
>> should not be able to retrieve private members when allMembers trait is
>
> Can you use a string instead of getMember?

You mean something like this:

foreach (member; __traits(allMembers, TestClass))
{
    static if (member == "value")
    {
        pragma(msg, __traits(getProtection, member));
    }
}

That works, but it prints "public", even though the "value" member is private. Surprisingly strange behavior
June 21, 2013
On 06/21/13 15:27, Martin wrote:
> On Friday, 21 June 2013 at 13:15:43 UTC, Jacob Carlborg wrote:
>> On 2013-06-21 15:04, Martin wrote:
>>> module test;
>>>
>>> void test()
>>> {
>>>
>>>
>>>     foreach (member; __traits(allMembers, Client))
>>>     {
>>>         pragma(msg, member); // Prints all members fine, including "value"
>>>     }
>>>
>>>     // This line fails
>>>     static if(__traits(getProtection, __traits(getMember, TestClass,
>>> "value")) == "public")
>>>     {
>>>         pragma(msg, "value is public");
>>>     }
>>>     else
>>>     {
>>>         pragma(msg, "value is not public");
>>>     }
>>>
>>> }
>>>
>>> module testclass;
>>>
>>> class TestClass
>>> {
>>> private:
>>>     int value;
>>> }
>>>
>>> When using the allMembers trait, the private "value" member of TestClass is included, but when trying to retrieve that member using the getMember trait, it fails to compile with test.d(13): Error: class main.TestClass member value is not accessible
>>>
>>> Is that intended behavior or a bug? I can't see why the getMember trait should not be able to retrieve private members when allMembers trait is
>>
>> Can you use a string instead of getMember?
> 
> You mean something like this:
> 
> foreach (member; __traits(allMembers, TestClass))
> {
>     static if (member == "value")
>     {
>         pragma(msg, __traits(getProtection, member));
>     }
> }
> 
> That works, but it prints "public", even though the "value" member is private. Surprisingly strange behavior

   pragma(msg, __traits(getProtection, mixin("TestClass." ~ member)));

artur

June 21, 2013
On Friday, 21 June 2013 at 13:42:44 UTC, Artur Skawina wrote:
> On 06/21/13 15:27, Martin wrote:
>> On Friday, 21 June 2013 at 13:15:43 UTC, Jacob Carlborg wrote:
>>> On 2013-06-21 15:04, Martin wrote:
>>>> module test;
>>>>
>>>> void test()
>>>> {
>>>>
>>>>
>>>>     foreach (member; __traits(allMembers, Client))
>>>>     {
>>>>         pragma(msg, member); // Prints all members fine, including "value"
>>>>     }
>>>>
>>>>     // This line fails
>>>>     static if(__traits(getProtection, __traits(getMember, TestClass,
>>>> "value")) == "public")
>>>>     {
>>>>         pragma(msg, "value is public");
>>>>     }
>>>>     else
>>>>     {
>>>>         pragma(msg, "value is not public");
>>>>     }
>>>>
>>>> }
>>>>
>>>> module testclass;
>>>>
>>>> class TestClass
>>>> {
>>>> private:
>>>>     int value;
>>>> }
>>>>
>>>> When using the allMembers trait, the private "value" member of TestClass
>>>> is included, but when trying to retrieve that member using the getMember
>>>> trait, it fails to compile with test.d(13): Error: class main.TestClass
>>>> member value is not accessible
>>>>
>>>> Is that intended behavior or a bug? I can't see why the getMember trait
>>>> should not be able to retrieve private members when allMembers trait is
>>>
>>> Can you use a string instead of getMember?
>> 
>> You mean something like this:
>> 
>> foreach (member; __traits(allMembers, TestClass))
>> {
>>     static if (member == "value")
>>     {
>>         pragma(msg, __traits(getProtection, member));
>>     }
>> }
>> 
>> That works, but it prints "public", even though the "value" member is private. Surprisingly strange behavior
>
>    pragma(msg, __traits(getProtection, mixin("TestClass." ~ member)));
>
> artur

Thanks, that sort of works. It prints "private" but then immediately gives an error:
test.d(12): Error: class main.TestClass member value is not accessible

Sigh, this is DMD 2.063.2 by the way.
June 21, 2013
On 2013-06-21 15:50, Martin wrote:

> Thanks, that sort of works. It prints "private" but then immediately
> gives an error:
> test.d(12): Error: class main.TestClass member value is not accessible
>
> Sigh, this is DMD 2.063.2 by the way.

That sucks. Time for a bugzilla report.

http://d.puremagic.com/issues/

-- 
/Jacob Carlborg
June 21, 2013
On 06/21/13 15:50, Martin wrote:
> On Friday, 21 June 2013 at 13:42:44 UTC, Artur Skawina wrote:
>>>    pragma(msg, __traits(getProtection, mixin("TestClass." ~ member)));
> Thanks, that sort of works. It prints "private" but then immediately gives an error: test.d(12): Error: class main.TestClass member value is not accessible
> 
> Sigh, this is DMD 2.063.2 by the way.

Sorry, didn't test that one, just used the right symbol; it has the same
problem as your original issue. Clearly, the getProtection trait wasn't
designed with inaccesible symbols in mind. And no, 'getMember' bypassing
the protection would not be a good idea (would make it too easy to mistakenly
access private data in generic code). getProtection should probably just
take two args, just like getMember, which would allow it to safely ignore
the normal access rules.

Right now, you can use 'tupleof', which bypasses the visibility attrs:

   alias T = TestClass;
   foreach (I, TYPE; typeof(T.tupleof)) {
        pragma(msg, __traits(getProtection, T.tupleof[I]), " ",
                    TYPE, " ",
                    __traits(identifier, T.tupleof[I]), ";");
   }

artur