digitalmars.D.learn - getSymbolsByUDA in constructor/member functions
- cc (28/28) Jun 15 2022 ```d
- frame (22/28) Jun 16 2022 I can only answer this partially, I guess `this` is just added
- Arafel (39/72) Jun 16 2022 I think it's a bug either in the `getSymbolsByUDA` implementation, or
- frame (6/12) Jun 16 2022 This is not true. `getMember` can return the symbol to the
- Arafel (25/34) Jun 16 2022 Classes can have static members just as structs, so I don't think you
- frame (22/29) Jun 16 2022 Maybe you are right. I also don't see why the `this` reference
- Paul Backus (4/7) Jun 16 2022 Yes, this is a compiler bug. I've filed a report for it on
```d import std.traits; class XML {} class Def { XML { int x; int y; } int z; this() { static foreach (sym; getSymbolsByUDA!(Def, XML)) { } } } void main() { auto def = new Def; } ``` ``` test.d(12): Error: value of `this` is not known at compile time test.d(12): Error: value of `this` is not known at compile time ``` Why doesn't this work? There is nothing in the foreach body. ```d alias ALL = getSymbolsByUDA!(Def, XML); pragma(msg, ALL.stringof); ``` reports `tuple(this.x, this.y)`. Why is `this.` added?
Jun 15 2022
On Wednesday, 15 June 2022 at 12:26:40 UTC, cc wrote:Why doesn't this work? There is nothing in the foreach body. ```d alias ALL = getSymbolsByUDA!(Def, XML); pragma(msg, ALL.stringof); ``` reports `tuple(this.x, this.y)`. Why is `this.` added?I can only answer this partially, I guess `this` is just added because `getSymbolsByUDA` want an instance but ` XML` is only seen as a type. As instance, you need to write ` XML()` instead: ```d class XML { static opCall() { return new XML(); } } class Def { XML() { int x; int y; } int z; this() { static foreach (sym; getSymbolsByUDA!(Def, XML)) { } } } ```
Jun 16 2022
On 15/6/22 14:26, cc wrote:```d import std.traits; class XML {} class Def { XML { int x; int y; } int z; this() { static foreach (sym; getSymbolsByUDA!(Def, XML)) { } } } void main() { auto def = new Def; } ``` ``` test.d(12): Error: value of `this` is not known at compile time test.d(12): Error: value of `this` is not known at compile time ``` Why doesn't this work? There is nothing in the foreach body. ```d alias ALL = getSymbolsByUDA!(Def, XML); pragma(msg, ALL.stringof); ``` reports `tuple(this.x, this.y)`. Why is `this.` added?I think it's a bug either in the `getSymbolsByUDA` implementation, or actually rather in the `__traits` system. A workaround bypassing `getSymbolsByUDA`: ```d import std.traits; import std.meta: Alias; class XML {} class Def { XML { int x; int y; } int z; this() { static foreach (sym; __traits(allMembers, Def)) {{ alias member = Alias!(__traits(getMember, Def, sym)); static if (hasUDA!(member, XML)) { pragma(msg, member.stringof); pragma(msg, sym); } }} } } void main() { auto def = new Def; } ``` As you can see, it's `getMember` who is returning a reference to the `this` instance. In my view, this is a bug according the documentation and examples [1]. It might be that classes behave differently, but then it should be documented. In fact, it shouldn't work at all and you'd need to instantiate Def: `getMember` should fail because `x` and `y` are not static. Interestingly, `hasUDA` (or rather `__traits(getAttributes, ...)`) later doesn't care about the dangling `this` reference, so I'm not sure who is to blame here... in any case, at the very least the documentation doesn't match the actual behavior. [1]: https://dlang.org/spec/traits.html#getMember
Jun 16 2022
On Thursday, 16 June 2022 at 08:23:20 UTC, Arafel wrote:As you can see, it's `getMember` who is returning a reference to the `this` instance. In my view, this is a bug according the documentation and examples [1]. It might be that classes behave differently, but then it should be documented.In fact, it shouldn't work at all and you'd need to instantiate Def: `getMember` should fail because `x` and `y` are not static.This is not true. `getMember` can return the symbol to the instance or the type/alias, depending if you pass `this` or `Def`. The last is static. It makes no sense to use the attribute from a class without an instance.
Jun 16 2022
On 16/6/22 10:55, frame wrote:On Thursday, 16 June 2022 at 08:23:20 UTC, Arafel wrote: This is not true. `getMember` can return the symbol to the instance or the type/alias, depending if you pass `this` or `Def`. The last is static. It makes no sense to use the attribute from a class without an instance.Classes can have static members just as structs, so I don't think you always need an instance for a class either. It seems the issue could be somewhere else: ``` import std.traits: getSymbolsByUDA; enum E; class C { E int a; pragma(msg, __traits(getMember,C,"a").stringof); // `a` void foo() { pragma(msg, C.stringof); // `C` pragma(msg, __traits(getMember,C,"a").stringof); // `this.C.a` // Fails here //static foreach (sym; getSymbolsByUDA!(C, E)) { } } // But works here static foreach (sym; getSymbolsByUDA!(C, E)) { } } ``` So if you call `getMember` from a member function, it adds the hidden `this` reference, and this has subtle consequences later on, even if `this.C` is practically just an alias for `C`. I still think this is a bug in `getMember`, although perhaps not as obvious as I first thought.
Jun 16 2022
On Thursday, 16 June 2022 at 09:29:36 UTC, Arafel wrote:Classes can have static members just as structs, so I don't think you always need an instance for a class either.Well, ok.So if you call `getMember` from a member function, it adds the hidden `this` reference, and this has subtle consequences later on, even if `this.C` is practically just an alias for `C`. I still think this is a bug in `getMember`, although perhaps not as obvious as I first thought.Maybe you are right. I also don't see why the `this` reference should be there in the static call. But it looks like a compiler bug since the output of `getSymbolsByUDA` is just an alias sequence and nothing should happen before consuming it? This works fine too: ```d class C { E int a; void foo() { alias seq = getSymbolsByUDA!(C, E); static foreach (i; 0 .. seq.length) { pragma(msg, hasUDA!(seq[i], E)); } } } ```
Jun 16 2022
On Thursday, 16 June 2022 at 13:27:25 UTC, frame wrote:But it looks like a compiler bug since the output of `getSymbolsByUDA` is just an alias sequence and nothing should happen before consuming it?Yes, this is a compiler bug. I've filed a report for it on bugzilla: https://issues.dlang.org/show_bug.cgi?id=23192
Jun 16 2022