September 03, 2016
On Saturday, September 03, 2016 19:30:54 Andrei Alexandrescu via Digitalmars-d wrote:
> On 9/3/16 6:39 PM, Andrej Mitrovic via Digitalmars-d wrote:
> > On 9/3/16, Martin Nowak via Digitalmars-d <digitalmars-d@puremagic.com>
wrote:
> >> On Wednesday, 31 August 2016 at 13:12:30 UTC, Adam D. Ruppe wrote:
> >>> Ugh, it really should just give everything and have getMember bypass it. That won't even break any code!
> >>
> >> It will, e.g. having getMember bypass protection means vibe.d would now serialize private members
> >
> > Then just add a check in vibe.d itself to avoid serializing private members. You can still call getProtection on the symbol and skip serializing it.
> >
> > Alternatively you can use UDAs so you can mark which fields should or shouldn't be serializible. For example https://github.com/msgpack/msgpack-d/blob/6046808c2e678e27cb2e2d9314241c36 1a6fd0ae/src/msgpack/attribute.d#L21
> >
> > The bottom line is with restricting access to private symbols you have no choice on the matter, while allowing access lets you specialize whether to ignore the symbols or not.
>
> I didn't follow this closely, but clearly we need some means to access private members for introspection purposes. I hope we don't paint ourselves out of that corner. -- Andrei

Well, that certainly seems to be exactly what we're doing with the changes that Ali is complaining about.

Previously __traits(allMembers, T) listed _all_ members, whereas now it wil only list the ones that are accessible. The same for __traits(derivedMembers, T). So, they'll still give you the private members if you use them inside the module in question but not elsewhere.

I would have thought that the way to handle this would be to have them list all members regardless of access level and then to have code check for the access level if it cares. I would have thought that doing stuff like looking at private symbols would be perfectly okay with no errors or deprecation warnings and that it would just be _accessing_ the symbol that would be disallowed and would require you to check for in code that used introspection. But clearly, there must be something that I misunderstand here, because that's not at all where this seems to be going.

I do get the feeling that too much of what we do with features like this is ad-hoc without really designing things up front, and then we keep having to tweak stuff as we go along in ways that aren't always particularly nice. And this particular change seems to just be a reaction to problems that we ran into with changing how imports work. And maybe it's the right choice, but it sure doesn't seem like it.

- Jonathan M Davis

September 03, 2016
On 09/03/2016 07:52 PM, Martin Nowak wrote:
> On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote:
>> I don't agree with the current solution:
> 
> Well let's come up with a better solution then.
> Let's start by finding some proper use-cases that require introspection
> on private members w/o having access to them.

Obviously serialization libraries come to mind, especially important for binary serialization because private members still affect the layout of the struct.



September 03, 2016
On 2016-09-03 17:50, Martin Nowak wrote:

> It will, e.g. having getMember bypass protection means vibe.d would now
> serialize private members
> https://github.com/rejectedsoftware/vibe.d/blob/c1180791de61d0f8c9bfb584c2551a5b64627e32/source/vibe/internal/meta/traits.d#L146.
>
> Until now getMember was just a DotIdExp (i.e. `T.indent`/`var.ident`),
> so it was used to test whether sth. can be accessed.

Without looking at the how the rest of the code works, it already checks if a member is public or not [1]. Or are you saying that "isPublicMember" would return a different value?

[1] https://github.com/rejectedsoftware/vibe.d/blob/c1180791de61d0f8c9bfb584c2551a5b64627e32/source/vibe/internal/meta/traits.d#L159

-- 
/Jacob Carlborg
September 03, 2016
On 2016-09-03 20:56, Dicebot wrote:

> Obviously serialization libraries come to mind, especially important for
> binary serialization because private members still affect the layout of
> the struct.

That can usually be solved using .tupleof[i], but I agree.

-- 
/Jacob Carlborg
September 03, 2016
On 9/3/16 7:57 PM, Jonathan M Davis via Digitalmars-d wrote:
> Previously __traits(allMembers, T) listed _all_ members, whereas now it wil
> only list the ones that are accessible. The same for
> __traits(derivedMembers, T). So, they'll still give you the private members
> if you use them inside the module in question but not elsewhere.

That... doesn't sound good. I wonder how such important changes slip by Walter and myself unnoticed.

My thinking is that the plebes should be able to access things via the object.member syntax by obeying the usual visibility rules. But __traits(allMembers, T) should be the reflection backdoor that gives the savvy users total access, at the obvious cost of an awkward syntax.

The fact that __traits(allMembers, T) compiles in all cases and has DIFFERENT semantics depending on whether T is in the same vs. a different module is the deadly sign of poor language design.

Martin, any chance we can undo this change to the language?


Andrei
September 03, 2016
On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote:
> Martin, any chance we can undo this change to the language?

The problem is deeper. If he undoes the change then what will happen again is that the results of allMembers won't be usable by the other traits, e.g getMember, because them are still limited by the protection attributes.


September 03, 2016
On 9/3/16 10:50 PM, Basile B. wrote:
> On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote:
>> Martin, any chance we can undo this change to the language?
>
> The problem is deeper. If he undoes the change then what will happen
> again is that the results of allMembers won't be usable by the other
> traits, e.g getMember, because them are still limited by the protection
> attributes.

Where are the past discussions on this matter? -- Andrei


September 03, 2016
On Saturday, 3 September 2016 at 20:54:19 UTC, Andrei Alexandrescu wrote:
> On 9/3/16 10:50 PM, Basile B. wrote:
>> On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote:
>>> Martin, any chance we can undo this change to the language?
>>
>> The problem is deeper. If he undoes the change then what will happen
>> again is that the results of allMembers won't be usable by the other
>> traits, e.g getMember, because them are still limited by the protection
>> attributes.
>
> Where are the past discussions on this matter? -- Andrei

The change in 2.071.2-beta3 to allMembers is designed to fix

https://issues.dlang.org/show_bug.cgi?id=15907

which happens because of a __traits(getMember,...) on the results of a __traits(allMembers,...).
September 03, 2016
On 2016-09-03 22:40, Andrei Alexandrescu wrote:

> That... doesn't sound good. I wonder how such important changes slip by
> Walter and myself unnoticed.

Here's the PR that introduced the change: https://github.com/dlang/dmd/pull/6078

-- 
/Jacob Carlborg
September 03, 2016
On Saturday, 3 September 2016 at 21:54:24 UTC, Jacob Carlborg wrote:
> Here's the PR that introduced the change: https://github.com/dlang/dmd/pull/6078

I'm certainly not going to upgrade to the next DMD if this change is retained. allMembers not returning all members makes introspection entirely useless when it comes to Binderoo.

The wrong conclusions were made from that bug to begin with it seems. allMembers should return all members. getProtection should report on the protection of a symbol *regardless* of whether getMember will succeed or not (this is currently why I have my PrivacyOf workaround - to stop the compiler crashing when using a template instead of a mixin template to do introspection).

getMember itself, well, I'd honestly prefer if there was a way to get to members without having to correlate with .tupleof as it will simplify Binderoo code. The .tupleof method doesn't help me when it comes to introspecting private/protected functions for C++ binding.