Thread overview
alias can't find symbol or can't use symbol
Apr 30, 2017
Carl Sturtivant
Apr 30, 2017
bauss
Apr 30, 2017
Carl Sturtivant
Apr 30, 2017
Jerry
May 03, 2017
Jonathan M Davis
May 04, 2017
Carl Sturtivant
May 06, 2017
Carl Sturtivant
May 06, 2017
Jonathan M Davis
April 30, 2017
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?



April 30, 2017
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 ...
}
```
April 30, 2017
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.

April 30, 2017
To me this seems like a bug.

May 03, 2017
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 04, 2017
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 06, 2017
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, 2017
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