August 30, 2016 Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | 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 Re: Usability of "allMembers and derivedMembers traits now only return visible symbols" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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?
|
Copyright © 1999-2021 by the D Language Foundation