www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Privacy violation depending on who passes a compile-time argument?

reply rcorre <ryan rcorre.net> writes:
Can someone help me understand why the first line is fine, but 
the second triggers a deprecation warning for access to a private 
variable?

---
import std.traits;
import s;

pragma(msg, hasUDA!(S.getMember_i, attr));   // fine
pragma(msg, hasUDA!(S.getMember!"i", attr)); // deprecated

/++ in module 's'
import std.traits;

struct attr { }

struct S {
    attr private int i;
   alias getMember(string name) = Identity!(__traits(getMember, S, 
name));
   alias getMember_i = getMember!"i";
}
++/
---

getMember is not a mixin template, so it seems like 
__traits(getMember, S, "i") should be resolved within the 's' 
module in both cases. Why is passing the string "i" from another 
module a violation even when getMember_i is doing the same thing 
internally?
Aug 14 2016
parent reply Basile B. <b2.temp gmx.com> writes:
On Sunday, 14 August 2016 at 12:03:28 UTC, rcorre wrote:
 Can someone help me understand why the first line is fine, but 
 the second triggers a deprecation warning for access to a 
 private variable?

 ---
 import std.traits;
 import s;

 pragma(msg, hasUDA!(S.getMember_i, attr));   // fine
 pragma(msg, hasUDA!(S.getMember!"i", attr)); // deprecated

 /++ in module 's'
 import std.traits;

 struct attr { }

 struct S {
    attr private int i;
   alias getMember(string name) = Identity!(__traits(getMember, 
 S, name));
   alias getMember_i = getMember!"i";
 }
 ++/
 ---

 getMember is not a mixin template, so it seems like 
 __traits(getMember, S, "i") should be resolved within the 's' 
 module in both cases.
No it's the opposite, only mixins gets the scope of the instantiation's location.
 Why is passing the string "i" from another module a violation 
 even when getMember_i is doing the same thing internally?
Try to compile this: struct S { private int i; int j; alias getMember(string name) = Identity!(__traits(getMember, S, name)); alias getMember_i = getMember!"i"; unittest { pragma(msg, __traits(getProtection, S.getMember!"i")); // private pragma(msg, __traits(getProtection, S.getMember!"j")); // public } } You'll see that this is even not a matter of module. Actually your "getMember" is not a member function, it's an alias to the source, i.e the same symbol with the same protection.
Aug 14 2016
parent reply rcorre <ryan rcorre.net> writes:
On Sunday, 14 August 2016 at 15:47:16 UTC, Basile B. wrote:
 No it's the opposite, only mixins gets the scope of the 
 instantiation's location.
Right, if it were a mixin, it would get the scope of the instantiation (the main module) and `i` would be inacessible. Since it isn't a mixin, I would expect the scope to be in module s, where it _can_ access `i`.
 Try to compile this:

 struct S
 {
     private int i;
     int j;
     alias getMember(string name) = 
 Identity!(__traits(getMember, S, name));
     alias getMember_i = getMember!"i";

     unittest
     {
         pragma(msg, __traits(getProtection, S.getMember!"i")); 
 // private
         pragma(msg, __traits(getProtection, S.getMember!"j")); 
 // public
     }
 }

 You'll see that this is even not a matter of module. Actually 
 your "getMember" is not a member function, it's an alias to the 
 source, i.e the same symbol with the same protection.
Ok, so S.getMember!"i" is really the same as S.i, so I get why it's private. But getMember_i is just an alias to that, so shouldn't it also be private? It makes sense if you accept the following: struct S { private int _i; alias i = i; } Which I used to accept without thinking about it, but now I'm wondering why that works.
Aug 14 2016
parent reply Basile B. <b2.temp gmx.com> writes:
On Sunday, 14 August 2016 at 16:34:48 UTC, rcorre wrote:
 On Sunday, 14 August 2016 at 15:47:16 UTC, Basile B. wrote:
 getMember_i is just an alias to that, so shouldn't it also be 
 private?
It is private: https://dpaste.dzfl.pl/83fcca84dde3, so the code you've posted in the first message could be a bug. The deprecation message also since this case has nothing to do with the transition period due to fix 314 (because your import is not selective).
Aug 14 2016
next sibling parent Basile B. <b2.temp gmx.com> writes:
On Sunday, 14 August 2016 at 17:23:06 UTC, Basile B. wrote:
 On Sunday, 14 August 2016 at 16:34:48 UTC, rcorre wrote:
 On Sunday, 14 August 2016 at 15:47:16 UTC, Basile B. wrote:
 getMember_i is just an alias to that, so shouldn't it also be 
 private?
It is private: https://dpaste.dzfl.pl/83fcca84dde3, so the code you've posted in the first message could be a bug. The deprecation message also since this case has nothing to do with the transition period due to fix 314 (because your import is not selective).
One thing that will make things worth in the near future: Identity has the "package" protection on phobos master... https://github.com/dlang/phobos/blob/master/std/traits.d#L3224 previously it was public (it's still in the latest public beta, which i use).
Aug 14 2016
prev sibling parent rcorre <ryan rcorre.net> writes:
On Sunday, 14 August 2016 at 17:23:06 UTC, Basile B. wrote:
 It is private: https://dpaste.dzfl.pl/83fcca84dde3, so the code 
 you've posted in the first message could be a bug.
Ah, you're correct. I'm not able to use either of them in runtime code.
 The deprecation message also since this case has nothing to do 
 with the transition period due to fix 314 (because your import 
 is not selective).
Makes sense. I still wonder whether using something like getUDAs on a symbol exposed like this is valid, but I guess that hasn't been decided yet (https://github.com/dlang/phobos/pull/4724#issuecomment-239424693). Thanks for the insights!
Aug 14 2016