Thread overview
[Issue 23907] __traits(child) respects visibility
May 08, 2023
Bolpat
May 09, 2023
RazvanN
May 09, 2023
Bolpat
May 08, 2023
https://issues.dlang.org/show_bug.cgi?id=23907

Bolpat <qs.il.paperinik@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |rejects-valid
                 CC|                            |qs.il.paperinik@gmail.com

--
May 09, 2023
https://issues.dlang.org/show_bug.cgi?id=23907

RazvanN <razvan.nitu1305@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |razvan.nitu1305@gmail.com

--- Comment #1 from RazvanN <razvan.nitu1305@gmail.com> ---
> This is consistent with other reflection traits

Which ones? I tried getMember and that doesn't bypass private.

I would argue that this is intended behavior and if the opposite occurs for other traits then that is the bug.

--
May 09, 2023
https://issues.dlang.org/show_bug.cgi?id=23907

--- Comment #2 from Bolpat <qs.il.paperinik@gmail.com> ---
> I would argue that this is intended behavior and if the opposite occurs for other traits then that is the bug.

I strongly disagree.

If you were right, that would mean that you cannot e.g. create a serialization library that can serialize private data members.

A module could reasonably pass a private symbol as an argument to an `alias` parameter of a template imported from another module. That template should be able to do its job, regardless whether the symbol is private.

> Which ones?

* `getProtection` for a trivial one.
* `getOverloads` allows accessing private overloads in a private aggregate
* `hasMember` and `allMembers` returns/lists private members
* `hasCopyConstructor` does not fail if the argument is an alias to a private
struct

I didn’t check all of them, just a sample.

> I tried `getMember` and that doesn't bypass private.

I have no idea what you tried, but in my tests, it does.

Here is what I tried (suitable for run.dlang.io):
```d
--- a.d
#line 3 "a.d"

private struct _S
{
    private int x;
    private void f() @safe {}
    private static int f(int x) @safe pure => x;
}

// only way to access anything in this module:
alias S = _S;

--- playground.d
#line 16 "playground.d"
import a;

void main()
{
    S s;
    static foreach (ov; __traits(getOverloads, s, "f"))
    {
        static if (is(typeof(ov(0))))
        {
            ov(0);
        }
    }
    static assert(__traits(hasMember, S, "f"));
    static assert(__traits(hasMember, s, "f"));
    static assert(!__traits(compiles, s.x = 2 )); // x is private
    __traits(getMember, s, "x") = 2;
    static assert(!__traits(compiles, assert(s.x == 2) )); // x is private
    assert(__traits(getMember, s, "x") == 2);
    static assert(__traits(getProtection, S) == "private");
    static assert(__traits(getProtection, __traits(getMember, s, "x")) ==
"private");
}
```

--