www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why can we not use __traits across protection?

reply Alex <AJ gmail.com> writes:
Module X:

class x
{
    private int x;
}

Module Y:

import X;

moduleName!(x.x);

or

__traits(getProtection, x.x);

Deprecation: `X.x.x.x` is not visible from module `Y`
Error: class `X.x.x` member `x` is not accessible

My use case is a little more complicated but I have two issues.


1: I have to import the module even though the type passed is 
valid(I'm using templates which are passed the type with a module 
import and I'd expect the module import to be "passed" along with 
the type so that I don't have to import it to use __traits or 
reflection.

2. If a member is protected then __traits and others fails. This 
makes absolutely no sense. Protection is used for run time, not 
compile time. What is strange is private methods give a 
deprecation warning but private fields give a deprecation error.
Apr 02 2019
next sibling parent reply drug <drug2004 bk.ru> writes:
On 02.04.2019 17:56, Alex wrote:
 Module X:
 
 class x
 {
     private int x;
 }
 
 Module Y:
 
 import X;
 
 moduleName!(x.x);
 
 or
 
 __traits(getProtection, x.x);
 
 Deprecation: `X.x.x.x` is not visible from module `Y`
 Error: class `X.x.x` member `x` is not accessible
 
 My use case is a little more complicated but I have two issues.
 
 
 1: I have to import the module even though the type passed is valid(I'm 
 using templates which are passed the type with a module import and I'd 
 expect the module import to be "passed" along with the type so that I 
 don't have to import it to use __traits or reflection.
 
 2. If a member is protected then __traits and others fails. This makes 
 absolutely no sense. Protection is used for run time, not compile time. 
 What is strange is private methods give a deprecation warning but 
 private fields give a deprecation error.
 
 
Yes, it's known issue. I've spent rather much time to manage this. I do something like https://github.com/drug007/asdf/blob/the_last_changes/source/asdf/s rialization.d#L3008 (this branch is not merged upstream yet)
Apr 02 2019
parent reply Alex <AJ gmail.com> writes:
On Tuesday, 2 April 2019 at 15:50:29 UTC, drug wrote:
 On 02.04.2019 17:56, Alex wrote:
 Module X:
 
 class x
 {
     private int x;
 }
 
 Module Y:
 
 import X;
 
 moduleName!(x.x);
 
 or
 
 __traits(getProtection, x.x);
 
 Deprecation: `X.x.x.x` is not visible from module `Y`
 Error: class `X.x.x` member `x` is not accessible
 
 My use case is a little more complicated but I have two issues.
 
 
 1: I have to import the module even though the type passed is 
 valid(I'm using templates which are passed the type with a 
 module import and I'd expect the module import to be "passed" 
 along with the type so that I don't have to import it to use 
 __traits or reflection.
 
 2. If a member is protected then __traits and others fails. 
 This makes absolutely no sense. Protection is used for run 
 time, not compile time. What is strange is private methods 
 give a deprecation warning but private fields give a 
 deprecation error.
 
 
Yes, it's known issue. I've spent rather much time to manage this. I do something like https://github.com/drug007/asdf/blob/the_last_changes/source/asdf/s rialization.d#L3008 (this branch is not merged upstream yet)
private template isPublic(alias aggregate, string member) { static if (!is(Identity!(__traits(getMember, aggregate, member))) && __traits(compiles, { auto s = __traits(getProtection, __traits(getMember, aggregate, member)); })) enum isPublic = !__traits(getProtection, __traits(getMember, aggregate, member)).privateOrPackage; else enum isPublic = false; } How does that work to get around the problem? It seems all it does is return false if it fails and so assumes it to be private... but this doesn't work in other traits that fail.
Apr 02 2019
parent drug <drug2004 bk.ru> writes:
On 03.04.2019 3:57, Alex wrote:
 On Tuesday, 2 April 2019 at 15:50:29 UTC, drug wrote:
 
 
 private template isPublic(alias aggregate, string member)
 {
      static if (!is(Identity!(__traits(getMember, aggregate, member))) &&
                 __traits(compiles, { auto s =
__traits(getProtection, 
 __traits(getMember, aggregate, member)); }))
              enum isPublic = !__traits(getProtection, 
 __traits(getMember, aggregate, member)).privateOrPackage;
      else
          enum isPublic = false;
 }
 
 How does that work to get around the problem? It seems all it does is 
 return false if it fails and so assumes it to be private...
 
 but this doesn't work in other traits that 
Ok, my usecase is the following - I need to process all members of some aggregate. But using traits with not accessible members fails. So I use `isPublic` to filter out not accessible members and then use other traits to process accessible members.
Apr 03 2019
prev sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Tuesday, 2 April 2019 at 14:56:38 UTC, Alex wrote:
 Module X:

 class x
 {
    private int x;
 }

 Module Y:

 import X;

 moduleName!(x.x);

 or

 __traits(getProtection, x.x);

 Deprecation: `X.x.x.x` is not visible from module `Y`
 Error: class `X.x.x` member `x` is not accessible

 My use case is a little more complicated but I have two issues.
__traits(getProtection, __traits(getMember, x, "x")) works. You just can't spell "x.x" anywhere.
 1: I have to import the module even though the type passed is 
 valid(I'm using templates which are passed the type with a 
 module import and I'd expect the module import to be "passed" 
 along with the type so that I don't have to import it to use 
 __traits or reflection.
I used to think this but it's not actually needed.
 2. If a member is protected then __traits and others fails. 
 This makes absolutely no sense. Protection is used for run 
 time, not compile time. What is strange is private methods give 
 a deprecation warning but private fields give a deprecation 
 error.
See above.
Apr 03 2019
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/3/19 5:19 AM, Atila Neves wrote:
 On Tuesday, 2 April 2019 at 14:56:38 UTC, Alex wrote:
 Module X:

 class x
 {
    private int x;
 }

 Module Y:

 import X;

 moduleName!(x.x);

 or

 __traits(getProtection, x.x);

 Deprecation: `X.x.x.x` is not visible from module `Y`
 Error: class `X.x.x` member `x` is not accessible

 My use case is a little more complicated but I have two issues.
__traits(getProtection, __traits(getMember, x, "x")) works. You just can't spell "x.x" anywhere.
So this is quite unintuitive. The compiler should realize here you are just checking protection, and forego the protection check on the expression. I.e. there should be a special exception to visibility checking inside __traits(getProtection, ...). -Steve
Apr 15 2019
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 15 April 2019 at 14:55:36 UTC, Steven Schveighoffer 
wrote:
 So this is quite unintuitive. The compiler should realize here 
 you are just checking protection, and forego the protection 
 check on the expression.
So there was a PR pulled last week that exempts getMember from protection checks, which solves this (finally!) and makes private filtering a user concern for the traits now. That is kinda cool. I got used to it the way before but this will prolly be more convenient overall.
Apr 15 2019