Jump to page: 1 28  
Page
Thread overview
Usability of "allMembers and derivedMembers traits now only return visible symbols"
Aug 30, 2016
Ali Çehreli
Aug 30, 2016
Basile B.
Aug 31, 2016
Basile B.
Aug 31, 2016
Ethan Watson
Aug 31, 2016
Adam D. Ruppe
Aug 30, 2016
Andrej Mitrovic
Aug 31, 2016
Jacob Carlborg
Aug 31, 2016
Andrej Mitrovic
Aug 31, 2016
Jacob Carlborg
Aug 31, 2016
ketmar
Sep 03, 2016
Martin Nowak
Sep 03, 2016
ketmar
Sep 03, 2016
Martin Nowak
Aug 31, 2016
Ethan Watson
Aug 31, 2016
Basile B.
Aug 31, 2016
Ethan Watson
Aug 31, 2016
Ethan Watson
Aug 31, 2016
Adam D. Ruppe
Aug 31, 2016
Basile B.
Sep 01, 2016
Basile B.
Sep 03, 2016
Martin Nowak
Sep 03, 2016
Martin Nowak
Sep 03, 2016
Andrej Mitrovic
Sep 03, 2016
Jonathan M Davis
Sep 03, 2016
Basile B.
Sep 03, 2016
Basile B.
Sep 03, 2016
Jacob Carlborg
Sep 03, 2016
Ethan Watson
Sep 07, 2016
Ali Çehreli
Sep 08, 2016
Chris Wright
Sep 04, 2016
Walter Bright
Sep 04, 2016
Martin Nowak
Sep 04, 2016
Stefan Koch
Sep 04, 2016
Martin Nowak
Sep 04, 2016
Johannes Pfau
Sep 04, 2016
Jacob Carlborg
Sep 04, 2016
David Nadlinger
Sep 04, 2016
David Nadlinger
Sep 05, 2016
Johannes Pfau
Sep 05, 2016
Alexandru Ermicioi
Sep 07, 2016
Ali Çehreli
Sep 07, 2016
Ali Çehreli
Sep 04, 2016
Martin Nowak
Sep 03, 2016
Jacob Carlborg
Aug 31, 2016
Jonathan M Davis
Aug 31, 2016
Ali Çehreli
Sep 03, 2016
Martin Nowak
Sep 07, 2016
Ali Çehreli
Sep 13, 2016
Martin Nowak
Sep 03, 2016
Martin Nowak
Sep 03, 2016
Martin Nowak
Sep 03, 2016
Basile B.
Sep 04, 2016
Martin Nowak
Sep 04, 2016
Basile B.
Sep 04, 2016
Martin Nowak
Sep 04, 2016
Basile B.
Sep 04, 2016
Jacob Carlborg
Sep 03, 2016
Dicebot
Sep 03, 2016
Jacob Carlborg
Sep 04, 2016
Martin Nowak
Sep 05, 2016
Jacob Carlborg
Sep 07, 2016
Johan Engelen
Sep 07, 2016
Basile B.
Sep 04, 2016
Martin Nowak
Sep 04, 2016
Martin Nowak
Sep 05, 2016
Martin Nowak
Sep 05, 2016
Jacob Carlborg
Sep 07, 2016
Ali Çehreli
Sep 14, 2016
earthfront
August 30, 2016
v2.071.2-b3 is bringing a change for this bug:

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

I don't agree with the current solution:

  http://dlang.org/changelog/2.071.2.html#traits-members-visibility

Modules should be able to use library templates without needing to mix them in first.

Do you think the solution in the change log usable? I don't think so because silently skipping my private members is an unexpected behavior that will cause bugs.

Further, do I understand the example right? Am I supposed to mixin the same template twice for two different types? The following code which adds another struct does not compile:

import std.stdio;
import std.traits;

enum UDA;
struct S
{
    @UDA int visible;
    @UDA private int invisible;
}

// only returns symbols visible from std.traits
static assert(getSymbolsByUDA!(S, UDA).length == 1);
// mixin the template instantiation, using a name to avoid namespace pollution
mixin getSymbolsByUDA!(S, UDA) symbols;
// as the template is instantiated in the current scope, it can see private members
static assert(symbols.getSymbolsByUDA.length == 2);

// --- The following is added by Ali: ---

struct S2 {
    @UDA int s2;
}

mixin getSymbolsByUDA!(S2, UDA) symbolsS2;    // COMPILATION ERROR:
// Error: mixin deneme.getSymbolsByUDA!(S2, UDA) TList isn't a template

static assert(symbolsS2.getSymbolsByUDA.length == 1);

void main() {
    foreach (i; 0 .. symbols.getSymbolsByUDA.length) {
        // ...
    }
}

I can't wrap my head around the fact that a library template called by my module cannot see my private members.

Ali
August 30, 2016
On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote:
> v2.071.2-b3 is bringing a change for this bug:
>
>   https://issues.dlang.org/show_bug.cgi?id=15907
>
> I don't agree with the current solution:
>
>   http://dlang.org/changelog/2.071.2.html#traits-members-visibility
>
> Modules should be able to use library templates without needing to mix them in first.
>
> Do you think the solution in the change log usable? I don't think so because silently skipping my private members is an unexpected behavior that will cause bugs.
>
> Further, do I understand the example right? Am I supposed to mixin the same template twice for two different types? The following code which adds another struct does not compile:
>
> import std.stdio;
> import std.traits;
>
> enum UDA;
> struct S
> {
>     @UDA int visible;
>     @UDA private int invisible;
> }
>
> // only returns symbols visible from std.traits
> static assert(getSymbolsByUDA!(S, UDA).length == 1);
> // mixin the template instantiation, using a name to avoid namespace pollution
> mixin getSymbolsByUDA!(S, UDA) symbols;
> // as the template is instantiated in the current scope, it can see private members
> static assert(symbols.getSymbolsByUDA.length == 2);
>
> // --- The following is added by Ali: ---
>
> struct S2 {
>     @UDA int s2;
> }
>
> mixin getSymbolsByUDA!(S2, UDA) symbolsS2;    // COMPILATION ERROR:
> // Error: mixin deneme.getSymbolsByUDA!(S2, UDA) TList isn't a template
>
> static assert(symbolsS2.getSymbolsByUDA.length == 1);
>
> void main() {
>     foreach (i; 0 .. symbols.getSymbolsByUDA.length) {
>         // ...
>     }
> }
>
> I can't wrap my head around the fact that a library template called by my module cannot see my private members.
>
> Ali

Yes I agree, a change of the specifications in a dot release seems a bit extreme, especially since there was a deeper problem **before** the broken imports were fixed.

This problem was discovered a while back when the library traits related to UDAs were added to phobos.

The little story began here: https://issues.dlang.org/show_bug.cgi?id=15335. Then the proposal to give super powers to certain traits verbs: https://issues.dlang.org/show_bug.cgi?id=15371.
August 31, 2016
On 8/31/16, Ali Çehreli via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> mixin getSymbolsByUDA!(S, UDA) symbols;

This is such a bizarre workaround to be listed in the changelog since mixing in non-mixin templates is not an official feature (am I wrong?). getSymbolsByUDA is a template, not a mixin template.

August 31, 2016
On 8/31/16, Ali Çehreli via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> v2.071.2-b3 is bringing a change for this bug:
>
>    https://issues.dlang.org/show_bug.cgi?id=15907

PSA: If all one cares about are UDAs for fields and not functions then .tupleof is still a viable workaround. Working example:

-----
import getSymbols;

enum UDA;

struct S
{
    @UDA float visible;

    float dont_care;

    private @UDA int invisible;
}

void main()
{
    static assert(getSymbolsByUDA!(S, UDA).length == 2);
    static assert(getSymbolsByUDA!(S, UDA).stringof == "tuple(visible,
invisible)");
}
-----

-----
module getSymbols;

import std.meta : AliasSeq;
import std.traits : staticIndexOf;

template getSymbolsByUDA ( T, alias uda )
{
    alias getSymbolsByUDA = getSymbolsByUDAImpl!(T, uda);
}

template getSymbolsByUDAImpl ( T, alias uda, size_t idx = 0 )
{
    static if (idx + 1 < T.tupleof.length)
    {
        static if (hasUDA!(T.tupleof[idx], uda))
            alias Field = AliasSeq!(T.tupleof[idx]);
        else
            alias Field = AliasSeq!();

        alias getSymbolsByUDAImpl = AliasSeq!(Field,
            getSymbolsByUDAImpl!(T, uda, idx + 1));
    }
    else
    {
        static if (hasUDA!(T.tupleof[idx], uda))
            alias getSymbolsByUDAImpl = AliasSeq!(T.tupleof[idx]);
        else
            alias getSymbolsByUDAImpl = AliasSeq!();
    }
}

template hasUDA ( alias field, alias uda )
{
    enum hasUDA = staticIndexOf!(uda, __traits(getAttributes, field)) != -1;
}
-----

This is the reason msgpack-d still works and wasn't broken by the change.

August 31, 2016
On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote:
yeah, the whole feature smells for me. the sole need of mixin hack indicates that something is very wrong here. i never ever needed that for normal D code. and now suddenly i have to remember that some thing is a template, that it needs mixing it to work properly, etc.

all this mess should be resolved in compiler by assigning template *two* visibility scopes: one is template's "normal" scope (so it can see symbols from it's originating module), and second is it's "instantiation" scope. after all, this is exactly what programmer is exepecting. current solution is not a solution at all, it's a hacky workaround promoted to "official technique".
August 31, 2016
On 2016-08-31 01:01, Andrej Mitrovic via Digitalmars-d wrote:

> This is such a bizarre workaround to be listed in the changelog since
> mixing in non-mixin templates is not an official feature (am I
> wrong?).

Yes. Originally one could not use the "mixin" keyword in front of a template. There was no difference between mixin templates and non-mixin templates, on the declaration site. Later the language was changed to allow to put "mixin" in front of a template. That restricted all mixin templates to only be used as mixin templates. It's still possible to mixin non-mixin templates, most likely to avoid breaking existing code.

-- 
/Jacob Carlborg
August 31, 2016
On 2016-08-31 02:16, Andrej Mitrovic via Digitalmars-d wrote:

> PSA: If all one cares about are UDAs for fields and not functions then
> .tupleof is still a viable workaround. Working example:
>
> -----
> import getSymbols;
>
> enum UDA;
>
> struct S
> {
>     @UDA float visible;
>
>     float dont_care;
>
>     private @UDA int invisible;
> }
>
> void main()
> {
>     static assert(getSymbolsByUDA!(S, UDA).length == 2);
>     static assert(getSymbolsByUDA!(S, UDA).stringof == "tuple(visible,
> invisible)");
> }
> -----
>
> -----
> module getSymbols;
>
> import std.meta : AliasSeq;
> import std.traits : staticIndexOf;
>
> template getSymbolsByUDA ( T, alias uda )
> {
>     alias getSymbolsByUDA = getSymbolsByUDAImpl!(T, uda);
> }
>
> template getSymbolsByUDAImpl ( T, alias uda, size_t idx = 0 )
> {
>     static if (idx + 1 < T.tupleof.length)
>     {
>         static if (hasUDA!(T.tupleof[idx], uda))
>             alias Field = AliasSeq!(T.tupleof[idx]);
>         else
>             alias Field = AliasSeq!();
>
>         alias getSymbolsByUDAImpl = AliasSeq!(Field,
>             getSymbolsByUDAImpl!(T, uda, idx + 1));
>     }
>     else
>     {
>         static if (hasUDA!(T.tupleof[idx], uda))
>             alias getSymbolsByUDAImpl = AliasSeq!(T.tupleof[idx]);
>         else
>             alias getSymbolsByUDAImpl = AliasSeq!();
>     }
> }
>
> template hasUDA ( alias field, alias uda )
> {
>     enum hasUDA = staticIndexOf!(uda, __traits(getAttributes, field)) != -1;
> }
> -----
>
> This is the reason msgpack-d still works and wasn't broken by the change.

Ah, nice workaround. Last time I tried to use __traits(getAttributes) with a "tupleof expression" it didn't work.

-- 
/Jacob Carlborg
August 31, 2016
On Tuesday, 30 August 2016 at 22:46:58 UTC, Basile B. wrote:
> On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote:
>> v2.071.2-b3 is bringing a change for this bug:
>>
>
> Yes I agree, a change of the specifications in a dot release seems a bit extreme, especially since there was a deeper problem **before** the broken imports were fixed.
>
> This problem was discovered a while back when the library traits related to UDAs were added to phobos.
>
> The little story began here: https://issues.dlang.org/show_bug.cgi?id=15335. Then the proposal to give super powers to certain traits verbs: https://issues.dlang.org/show_bug.cgi?id=15371.

To be clear, the logic I see for traits "getMember", "allMember", "getOverloads", "derivedMembers" (etc, all the traits that might be today limited by the protection attribute) is:

allow them to see everything, then use "getProtection" if you wanna be conform with the protection attributes.

Maybe it's worth a DIP ? Casual and informal discussions have **failed**.

I see now the answer that mentions ".tupleof". I see no valid logic that would allow ".tupleof" to see everything and not the traits.
August 31, 2016
On Wednesday, 31 August 2016 at 08:06:05 UTC, Basile B. wrote:
> allow them to see everything, then use "getProtection" if you wanna be conform with the protection attributes.

That's how it used to work, but getProtection would fail if the symbol wasn't public. Which led to me using a workaround to something of this effect:

enum PrivacyLevel : string
{
	Public			= "public",
	Private			= "private",
	Protected		= "protected",
	Export			= "export",
	Package			= "package",
	Inaccessible		= "inaccessible"
};
//----------------------------------------------------------------------------

template PrivacyOf( alias symbol )
{
	static if( __traits( compiles, __traits( getProtection, symbol ) ) )
	{
		enum PrivacyOf = cast(PrivacyLevel) __traits( getProtection, symbol );
	}
	else
	{
		enum PrivacyOf = PrivacyLevel.Inaccessible;
	}
}
//----------------------------------------------------------------------------

Still not an ideal solution - because if I'm trying to serialise and deserialise everything in between module reloads I still need to do the .tupleof method to get all data members; and if I want to define privacy levels for functions I'm automatically binding from C++ I need to muddy those waters with UDAs etc.
August 31, 2016
On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote:
> I don't agree with the current solution:

I'm somewhat surprised myself that "allMembers doesn't return all members" needs highlighting.

Why not have a new trait "allVisibleMembers" and just fix the privacy issues?
« First   ‹ Prev
1 2 3 4 5 6 7 8