www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - getSymbolsByUDA in constructor/member functions

reply cc <cc nevernet.com> writes:
```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
next sibling parent frame <frame86 live.com> writes:
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
prev sibling parent reply Arafel <er.krali gmail.com> writes:
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
parent reply frame <frame86 live.com> writes:
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
parent reply Arafel <er.krali gmail.com> writes:
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
parent reply frame <frame86 live.com> writes:
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
parent Paul Backus <snarwin gmail.com> writes:
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