www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - alias can't find symbol or can't use symbol

reply Carl Sturtivant <sturtivant gmail.com> writes:
Consider the following.

struct member
{
     int n;
}

struct outer
{
     member x;
     alias x this;
     alias n2 = n;
}

This does not compile: alias n2 = n;
Error: undefined identifier 'n'

On the other hand if change that into
     alias n2 = x.n;
then it does compile.

void main()
{
     outer o;
     o.n2 = 5;
}

Now this code doesn't compile: o.n2 = 5;
Error: need 'this' for 'n' of type 'int'

Given that one struct inside another is a static situation, this 
seems unnecessarily strict. It's getting in the way of some name 
management with `alias this`. What's the rationale here?
Apr 29
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Sunday, 30 April 2017 at 00:17:37 UTC, Carl Sturtivant wrote:
 Consider the following.

 struct member
 {
     int n;
 }

 struct outer
 {
     member x;
     alias x this;
     alias n2 = n;
 }

 This does not compile: alias n2 = n;
 Error: undefined identifier 'n'

 On the other hand if change that into
     alias n2 = x.n;
 then it does compile.

 void main()
 {
     outer o;
     o.n2 = 5;
 }

 Now this code doesn't compile: o.n2 = 5;
 Error: need 'this' for 'n' of type 'int'

 Given that one struct inside another is a static situation, 
 this seems unnecessarily strict. It's getting in the way of 
 some name management with `alias this`. What's the rationale 
 here?
What exactly did you expect here? 'n' is not in the scope of 'outer'. 'n' is in the scope of 'member'. Of course it works with 'x.n' since 'x' points to the 'member' declared inside 'outer'. I mean it would have worked with classes, but structs are different does not have any type of actual inheritance, which is what you're trying to achieve. ``` class member { int n; } class outer : member { alias n2 = n; // Ok ... } ```
Apr 29
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Sunday, 30 April 2017 at 02:19:29 UTC, bauss wrote:
 What exactly did you expect here?

 'n' is not in the scope of 'outer'.

 'n' is in the scope of 'member'.

 Of course it works with 'x.n' since 'x' points to the 'member' 
 declared inside 'outer'.

 I mean it would have worked with classes, but structs are 
 different does not have any type of actual inheritance, which 
 is what you're trying to achieve.

 ```
 class member {
     int n;
 }

 class outer : member {
     alias n2 = n; // Ok ...
 }
 ```
It did NOT work with x.n as I asserted. And `alias x this` brings n into the scope of outer. So your reply makes no sense.
Apr 30
prev sibling next sibling parent Jerry <Kickupx gmail.com> writes:
To me this seems like a bug.
Apr 30
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, 30 April 2017 at 00:17:37 UTC, Carl Sturtivant wrote:
 Consider the following.

 struct member
 {
     int n;
 }

 struct outer
 {
     member x;
     alias x this;
     alias n2 = n;
 }

 This does not compile: alias n2 = n;
 Error: undefined identifier 'n'
That makes perfect sense, as n is not in the scope of outer.
 On the other hand if change that into
     alias n2 = x.n;
 then it does compile.

 void main()
 {
     outer o;
     o.n2 = 5;
 }

 Now this code doesn't compile: o.n2 = 5;
 Error: need 'this' for 'n' of type 'int'

 Given that one struct inside another is a static situation, 
 this seems unnecessarily strict. It's getting in the way of 
 some name management with `alias this`. What's the rationale 
 here?
I believe that the core problem is that an alias declaration just aliases a symbol - i.e. it just creates a new name for the symbol. And as far as I can tell, alias n2 = x2.n; is actually equivalent to alias n2 = member.n; You get exactly the same error message if that change is made. It's a bit like how you can call a static function with an object rather than the struct/class(e.g. s.foo() instead of S.foo()). Similarly, if you turn n into a member function, then you get an error like q.d(20): Error: this for n needs to be type member not type outer It's just aliasing the function, not creating a delegate or doing a syntactic conversion. If it _were_ doing a syntactic conversion and just making it so that everywhere you see n2, it got changed to x.n, then I could see code like outer o; o.n2 = 5; working. But that's not how alias declarations work. They just create a new name for the symbol in the scope that they're declared. So, the symbol isn't tied to a particular instance, and you get the problem that you're having. alias this is a bit different, because it isn't really aliasing the symbol - rather it's telling the compiler about an implicit conversion. So, that arguably confuses things a bit, but for your example to work, normal alias declarations would need to do more than create a new name for a symbol, and as I understand it, they don't. Now, I totally agree that it would be nice if your example would work, and I think that I've run into this problem before in my own code, but aliases would have to work a bit differently than they curently do for it to work. It seems like a reasonable enhancement request to me, but I'm not sure what Walter's take on it would be. He has a tendancy to see things how the compiler would in cases like this and not necessarily how a typical programmer would, so it wouldn't surprise me if he's reaction were that of course it wouldn't work, but I don't know. It's often the case that what the programmer thinks is intuitive doesn't really jive with how the language actually works.
May 03
next sibling parent Carl Sturtivant <sturtivant gmail.com> writes:
On Wednesday, 3 May 2017 at 09:04:07 UTC, Jonathan M Davis wrote:
 I believe that the core problem is that an alias declaration 
 just aliases a symbol - i.e. it just creates a new name for the 
 symbol. And as far as I can tell,

 alias n2 = x2.n;

 is actually equivalent to

 alias n2 = member.n;

 You get exactly the same error message if that change is made. 
 It's a bit like how you can call a static function with an 
 object rather than the struct/class(e.g. s.foo() instead of 
 S.foo()). Similarly, if you turn n into a member function, then 
 you get an error like

 q.d(20): Error: this for n needs to be type member not type 
 outer

 It's just aliasing the function, not creating a delegate or 
 doing a syntactic conversion. If it _were_ doing a syntactic 
 conversion and just making it so that everywhere you see n2, it 
 got changed to x.n, then I could see code like

 outer o;
 o.n2 = 5;

 working. But that's not how alias declarations work. They just 
 create a new name for the symbol in the scope that they're 
 declared. So, the symbol isn't tied to a particular instance, 
 and you get the problem that you're having.

 alias this is a bit different, because it isn't really aliasing 
 the symbol - rather it's telling the compiler about an implicit 
 conversion. So, that arguably confuses things a  bit, but for 
 your example to work, normal alias declarations would need to 
 do more than create a new name for a symbol, and as I 
 understand it, they don't.

 Now, I totally agree that it would be nice if your example 
 would work, and I think that I've run into this problem before 
 in my own code, but aliases would have to work a bit 
 differently than they curently do for it to work. It seems like 
 a reasonable enhancement request to me, but I'm not sure what 
 Walter's take on it would be. He has a tendancy to see things 
 how the compiler would in cases like this and not necessarily 
 how a typical programmer would, so it wouldn't surprise me if 
 he's reaction were that of course it wouldn't work, but I don't 
 know. It's often the case that what the programmer thinks is 
 intuitive doesn't really jive with how the language actually 
 works.
Thanks, that was enlightening. That said, if alias this really did bring n into the outer scope in the specific case when it's a variable in an embedded struct then `alias n2 = n` in the outer scope would work in the ordinary way. After all, struct fakeOuter { int n; alias n2 = n; } void main() { fakeOuter o; o.n2 = 5; } compiles and runs fine. And presumably as it's a struct being embedded here struct member { int n; } struct outer { member x; alias x this; //alias n2 = n; } the binary layouts of fakeOuter and outer are the same, so the rename is harmless because it has a simple interpretation in regular D without `alias this`.
May 04
prev sibling parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Wednesday, 3 May 2017 at 09:04:07 UTC, Jonathan M Davis wrote:
 I believe that the core problem is that an alias declaration 
 just aliases a symbol - i.e. it just creates a new name for the 
 symbol. And as far as I can tell,

 alias n2 = x2.n;

 is actually equivalent to

 alias n2 = member.n;

 You get exactly the same error message if that change is made. 
 It's a bit like how you can call a static function with an 
 object rather than the struct/class(e.g. s.foo() instead of 
 S.foo()). Similarly, if you turn n into a member function, then 
 you get an error like

 q.d(20): Error: this for n needs to be type member not type 
 outer

 It's just aliasing the function, not creating a delegate or 
 doing a syntactic conversion. If it _were_ doing a syntactic 
 conversion and just making it so that everywhere you see n2, it 
 got changed to x.n, then I could see code like

 outer o;
 o.n2 = 5;

 working. But that's not how alias declarations work. They just 
 create a new name for the symbol in the scope that they're 
 declared. So, the symbol isn't tied to a particular instance, 
 and you get the problem that you're having.
The following works with outer2 o; o.n2 = 5; so it's not static, i.e. n2 is tied to the instance here. struct outer2 { int n; alias n2 = n; } So it seems reasonable to have better semantics for an embedded struct with alias_this.
May 06
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Saturday, May 6, 2017 1:49:34 PM CEST Carl Sturtivant via Digitalmars-d-
learn wrote:
 On Wednesday, 3 May 2017 at 09:04:07 UTC, Jonathan M Davis wrote:
 I believe that the core problem is that an alias declaration
 just aliases a symbol - i.e. it just creates a new name for the
 symbol. And as far as I can tell,

 alias n2 = x2.n;

 is actually equivalent to

 alias n2 = member.n;

 You get exactly the same error message if that change is made.
 It's a bit like how you can call a static function with an
 object rather than the struct/class(e.g. s.foo() instead of
 S.foo()). Similarly, if you turn n into a member function, then
 you get an error like

 q.d(20): Error: this for n needs to be type member not type
 outer

 It's just aliasing the function, not creating a delegate or
 doing a syntactic conversion. If it _were_ doing a syntactic
 conversion and just making it so that everywhere you see n2, it
 got changed to x.n, then I could see code like

 outer o;
 o.n2 = 5;

 working. But that's not how alias declarations work. They just
 create a new name for the symbol in the scope that they're
 declared. So, the symbol isn't tied to a particular instance,
 and you get the problem that you're having.
The following works with outer2 o; o.n2 = 5; so it's not static, i.e. n2 is tied to the instance here. struct outer2 { int n; alias n2 = n; } So it seems reasonable to have better semantics for an embedded struct with alias_this.
But that's fundamentally different from what you were trying to do before. With struct outer2 { int n; alias n2 = n; } auter2 o; o.n2 = 5; the alias is an alias to something in the same scope which does not require a different this pointer/reference. No additional information is required. On the other hand, with struct A { int n; } struct B { B x; alias n2 = x.n; } A a; a.n2 = 5; it needs to use the member variable x to get at n. So, for that to work, it needs to do more than simply alias the symbol, since a symbol is not tied to an instance. I agree that it would be nice if both examples worked, but that isn't how alias declarations currently work. I don't know how hard it would be to talk Walter into changing it. It may be that he would be easy to convince, or it could be that he'd be against it. I don't know. - Jonathan M Davis
May 06