www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - This needs to be fixed

reply Manu <turkeyman gmail.com> writes:
alias x =3D s.tupleof; // this works
alias y =3D s.tupleof[0]; // this is a compile error?!

How can embarrassing edge cases like this still exist in the language today=
?
I'm just reacquainting myself with all the reasons that I've had such a
hard time trying to convince my colleagues to take D seriously for such a
long time.

=F0=9F=98=AB
Aug 24
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!

 How can embarrassing edge cases like this still exist in the 
 language today? I'm just reacquainting myself with all the 
 reasons that I've had such a hard time trying to convince my 
 colleagues to take D seriously for such a long time.

 😫
```d auto tuple(T...)(T args){ struct Tuple{ enum istuple=true; T me; alias me this; } return Tuple(args); } unittest{ auto foo=tuple(1,"hi"); assert(foo[0]==1); assert(foo[1]=="hi"); auto bar=tuple(); } auto totuple(T)(T a) if(is(typeof(a.istuple)))=>a; auto totuple(T)(T a) if( ! is(typeof(a.istuple)))=>tuple(a); auto maybetuple(T...)(T a){ static if(T.length==1){ return a[0]; } else { return tuple(a); }} ``` Could be fixed with a better std.meta
Aug 24
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Saturday, 24 August 2024 at 17:56:21 UTC, monkyyy wrote:
 On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!

 How can embarrassing edge cases like this still exist in the 
 language today? I'm just reacquainting myself with all the 
 reasons that I've had such a hard time trying to convince my 
 colleagues to take D seriously for such a long time.

 😫
```d auto tuple(T...)(T args){ struct Tuple{ enum istuple=true; T me; alias me this; } return Tuple(args); } unittest{ auto foo=tuple(1,"hi"); assert(foo[0]==1); assert(foo[1]=="hi"); auto bar=tuple(); } auto totuple(T)(T a) if(is(typeof(a.istuple)))=>a; auto totuple(T)(T a) if( ! is(typeof(a.istuple)))=>tuple(a); auto maybetuple(T...)(T a){ static if(T.length==1){ return a[0]; } else { return tuple(a); }} ``` Could be fixed with a better std.meta
D needs native tuple, not this mess
Aug 24
next sibling parent reply Manu <turkeyman gmail.com> writes:
On Sun, 25 Aug 2024 at 04:56, ryuukk_ via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Saturday, 24 August 2024 at 17:56:21 UTC, monkyyy wrote:
 On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:
 alias x =3D s.tupleof; // this works
 alias y =3D s.tupleof[0]; // this is a compile error?!

 How can embarrassing edge cases like this still exist in the
 language today? I'm just reacquainting myself with all the
 reasons that I've had such a hard time trying to convince my
 colleagues to take D seriously for such a long time.

 =F0=9F=98=AB
```d auto tuple(T...)(T args){ struct Tuple{ enum istuple=3Dtrue; T me; alias me this; } return Tuple(args); } unittest{ auto foo=3Dtuple(1,"hi"); assert(foo[0]=3D=3D1); assert(foo[1]=3D=3D"hi"); auto bar=3Dtuple(); } auto totuple(T)(T a) if(is(typeof(a.istuple)))=3D>a; auto totuple(T)(T a) if( ! is(typeof(a.istuple)))=3D>tuple(a); auto maybetuple(T...)(T a){ static if(T.length=3D=3D1){ return a[0]; } else { return tuple(a); }} ``` Could be fixed with a better std.meta
D needs native tuple, not this mess
Facts. This is a really old drum to beat on... but maybe we need to start pounding it again. It's not strictly this simple though; I think there's a lot of work up-front. We don't really even know what a tuple is, or even what "kinds" of things the language can express... Like, there's more than types and values. There's symbol aliases, which may or may not carry an instance reference with them, declaration aliases, which may carry names and properties like storage class, there's sometimes expression aliases, there's potentially attributes, and heaps of other stuff that exists outside the language; like storage class, which doesn't seem to have any presence in the language at all; it's queried with a __traits and comically tells you those facts as string literals! I think this space might be the heart and soul of D's foundational issues, and as such, it's excruciatingly hard to make corrections. Like, from my example above, what even IS `s.tupleof`? It's some kind of list of what kind of thing? Direct symbol references to members of a live instance? If s.tupleof can populate a list with that kind of thing, why doesn't this work: struct S { int x, y; } struct T { S s; int i; alias a =3D i; // works alias b =3D s.x; // Doesn't work? Why? } It seems like s.tupleof presents that there are semantics in the language to express this sort of thing, but it's not clear what to call that. Likewise in my example above: alias a =3D s.tupleof; // this can hold the list of references, which seem = to carry around their instance reference with them alias b =3D s.tupleof[0]; // this emits a surprising error message: error : alias `b` cannot alias an expression `AliasSeq!(s.x, s.y)[0]` So, that 'list' I mention; does this error message imply that this list given by `tupleof` is an AliasSeq? What exactly IS an AliasSeq? What is the actual set of things that it can hold? If tupleof is an AliasSeq, then what's going on here: alias c =3D AliasSeq!(s.tupleof); alias d =3D c[0]; // the error is now gone?? I think a good indication that this whole space is profoundly troubled when classic patterns like this emerge: template T(alias X) { use X } // oh no you don't, alias is very opinionated! you'll need this instead: template T(X...) if (X.length =3D=3D 1) { use X[0] } Who here can honestly say they thought that was a reasonable thing to write the first time they encountered that piece of comedy gold? ... and why are they even different things? If an AliasSeq isn't a sequence of aliases, what is it? What are people supposed to imagine it is? These are rhetorical questions, put yourself in an outside perspective; I know you can 'explain' it. I used to be able to explain it, but it turns out that with a few years off from D that toxicity in my mind seems to have subsided to some degree! I'm reacquainting myself with a sea of nonsense that I kinda just settled into with sufficient sustained exposure. No matter how you look at it though, this shouldn't be a valid forum post in 2024...
Aug 24
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Sunday, 25 August 2024 at 05:07:43 UTC, Manu wrote:
 This is a really old drum to beat on... but maybe we need to 
 start pounding
 it again.

 It's not strictly this simple though; I think there's a lot of 
 work up-front. We don't really even know what a tuple is, or 
 even what "kinds" of things the language can express...

 Like, there's more than types and values. There's symbol 
 aliases, which may or may not carry an instance reference with 
 them, declaration aliases, which may carry names and properties 
 like storage class, there's sometimes expression aliases, 
 there's potentially attributes, and heaps of other stuff that 
 exists outside the language; like storage class, which doesn't 
 seem to have any presence in the language at all; it's queried 
 with a __traits and comically tells you those facts as string 
 literals! I think this space might be the heart and soul of D's 
 foundational issues, and as such, it's excruciatingly hard to 
 make corrections.

 Like, from my example above, what even IS `s.tupleof`? It's 
 some kind of
 list of what kind of thing? Direct symbol references to members 
 of a live
 instance?
 If s.tupleof can populate a list with that kind of thing, why 
 doesn't this
 work:

 struct S
 {
   int x, y;
 }

 struct T
 {
   S s;
   int i;

   alias a = i; // works
   alias b = s.x; // Doesn't work? Why?
 }
All good points I think. AliasSeq and aliases in general have always been a sore spot in D meta.
 It seems like s.tupleof presents that there are semantics in 
 the language to express this sort of thing, but it's not clear 
 what to call that.

 Likewise in my example above:

 alias a = s.tupleof; // this can hold the list of references, 
 which seem to
 carry around their instance reference with them
 alias b = s.tupleof[0]; // this emits a surprising error 
 message:

 error : alias `b` cannot alias an expression `AliasSeq!(s.x, 
 s.y)[0]`

 So, that 'list' I mention; does this error message imply that 
 this list given by `tupleof` is an AliasSeq? What exactly IS an 
 AliasSeq? What is the actual set of things that it can hold?

 If tupleof is an AliasSeq, then what's going on here:

 alias c = AliasSeq!(s.tupleof);
 alias d = c[0]; // the error is now gone??
At first, I was thinking WTF is this? How can this work? But the answer is, it doesn't. if you try to *use* `d` you will get an error, because there is no instance -- you ended up aliasing the symbol without the instance. I almost feel like we need a distinction between alias-with-instance and alias-of-symbol. There are more WTFs, like in certain cases aliases will carry along names along with the types, and in some cases they don't. I remember classically this pattern (before static foreach): ```d foreach(i, _unused; x.tupleof) { // use x.tupleof[i] here instead of _unused, because the former gives names } ```
 I think a good indication that this whole space is profoundly 
 troubled when classic patterns like this emerge:

 template T(alias X) { use X }   // oh no you don't, alias is 
 very
 opinionated! you'll need this instead:
 template T(X...) if (X.length == 1) { use X[0] }
This is no longer needed, so at least there is a bit of progress.
 No matter how you look at it though, this shouldn't be a valid 
 forum post in 2024...
Agreed. -Steve
Aug 25
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Sunday, 25 August 2024 at 16:26:47 UTC, Steven Schveighoffer 
wrote:
 AliasSeq and aliases in general have always been a sore spot in 
 D meta.
Hard no, overload sets and auto flattening are super magic and just great. The spec and the book should just *have* explanations about the behavior
Aug 25
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Mon, 26 Aug 2024 at 02:31, Steven Schveighoffer via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 25 August 2024 at 05:07:43 UTC, Manu wrote:
 This is a really old drum to beat on... but maybe we need to
 start pounding
 it again.

 It's not strictly this simple though; I think there's a lot of
 work up-front. We don't really even know what a tuple is, or
 even what "kinds" of things the language can express...

 Like, there's more than types and values. There's symbol
 aliases, which may or may not carry an instance reference with
 them, declaration aliases, which may carry names and properties
 like storage class, there's sometimes expression aliases,
 there's potentially attributes, and heaps of other stuff that
 exists outside the language; like storage class, which doesn't
 seem to have any presence in the language at all; it's queried
 with a __traits and comically tells you those facts as string
 literals! I think this space might be the heart and soul of D's
 foundational issues, and as such, it's excruciatingly hard to
 make corrections.

 Like, from my example above, what even IS `s.tupleof`? It's
 some kind of
 list of what kind of thing? Direct symbol references to members
 of a live
 instance?
 If s.tupleof can populate a list with that kind of thing, why
 doesn't this
 work:

 struct S
 {
   int x, y;
 }

 struct T
 {
   S s;
   int i;

   alias a = i; // works
   alias b = s.x; // Doesn't work? Why?
 }
All good points I think. AliasSeq and aliases in general have always been a sore spot in D meta.
Indeed, and despite that, it's also quite likely that it is simultaneously also D's single most important and noteworthy feature! Above literally everything else by a country mile. I think every meaningful advantage that D brings to the table essentially stems from `alias` in some form, or this general realm of D's meta. I think it's really important to try and make a strong case that this stuff is of the most critical importance. There's fault lines and fractures all over the place; this category of issues should be addressed with a laser focus and ruthless murder... and it should have happened 15 years ago.
 It seems like s.tupleof presents that there are semantics in
 the language to express this sort of thing, but it's not clear
 what to call that.

 Likewise in my example above:

 alias a = s.tupleof; // this can hold the list of references,
 which seem to
 carry around their instance reference with them
 alias b = s.tupleof[0]; // this emits a surprising error
 message:

 error : alias `b` cannot alias an expression `AliasSeq!(s.x,
 s.y)[0]`

 So, that 'list' I mention; does this error message imply that
 this list given by `tupleof` is an AliasSeq? What exactly IS an
 AliasSeq? What is the actual set of things that it can hold?

 If tupleof is an AliasSeq, then what's going on here:

 alias c = AliasSeq!(s.tupleof);
 alias d = c[0]; // the error is now gone??
At first, I was thinking WTF is this? How can this work? But the answer is, it doesn't. if you try to *use* `d` you will get an error, because there is no instance -- you ended up aliasing the symbol without the instance.
Oh nice catch... But that just leads to the question; what's with `b` then? Why did `b` emit the error eagerly at the assignment, but `d` decided to take a lazy approach as you say? What I really want to know though; why do these aliases drop the instance? That's just a bug right? There's no reason you would want that behaviour, and it's obvious that an alias+instance reference *can* be carried by the AST, because it's there before it's unceremoniously dropped basically whenever you touch it.
 I think a good indication that this whole space is profoundly
 troubled when classic patterns like this emerge:

 template T(alias X) { use X }   // oh no you don't, alias is
 very
 opinionated! you'll need this instead:
 template T(X...) if (X.length == 1) { use X[0] }
This is no longer needed, so at least there is a bit of progress.
It's not? I just had to write an instance of this hack yesterday, for the same traditional reasons as ever... :/ What changed? I'll take another look at it.
Aug 25
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Sunday, 25 August 2024 at 17:27:33 UTC, Manu wrote:
 
 But that just leads to the question; what's with `b` then?
I believe its a struct offset I dont understand the usecase, but it goes into traits ``` struct S{ int x,y; } struct S_{ int y,x; } unittest{ import std; S s; alias b = s.x; S_ s_; __traits(child, s, b)=1;//works //__traits(child, s_, b)=1;//errors, when S_.y is also an int in the same place and a S_.x exists *grumble* } ```
 Why did `b` emit the error eagerly at the assignment, but `d` 
 decided to
 take a lazy approach as you say?
aliases can be lazy if they reference a lazy compilation error ```d alias Seq(T...)=T; template foo(int i){ void foo()(){ static if(i==1){ static assert(0); } import std; i.writeln; } } template bar(int i){ alias foobar=Seq!(foo!i); alias bar=foobar[0]; } unittest{ alias barfoo=bar!1; bar!2; } ```
Aug 25
prev sibling next sibling parent reply user1234 <user1234 12.de> writes:
On Sunday, 25 August 2024 at 17:27:33 UTC, Manu wrote:
 Oh nice catch...
 But that just leads to the question; what's with `b` then?
 Why did `b` emit the error eagerly at the assignment, but `d` 
 decided to
 take a lazy approach as you say?

 What I really want to know though; why do these aliases drop 
 the instance?
 That's just a bug right?
 There's no reason you would want that behaviour, and it's 
 obvious that an
 alias+instance reference *can* be carried by the AST, because 
 it's there
 before it's unceremoniously dropped basically whenever you 
 touch it.
Just in case, the kind of alias you are debating about is to be deprecated, see https://dlang.org/spec/legacy.html#alias-instance-member. It seems that what you are looking for is more a kind of system of parameter-less expression-macros. I have put a link to an old PR in a previous answer. You'll see that the main issue is that such aliases needs to be recontextualized for each new use.
Aug 25
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 8/25/24 21:35, user1234 wrote:
 
 Just in case, the kind of alias you are debating about is to be 
 deprecated, see https://dlang.org/spec/legacy.html#alias-instance-member.
Well, first it should be deprecated, then at some point it should just be made to work the way people would expect.
Aug 25
parent Nick Treleaven <nick geany.org> writes:
On Sunday, 25 August 2024 at 19:42:08 UTC, Timon Gehr wrote:
 On 8/25/24 21:35, user1234 wrote:
 
 Just in case, the kind of alias you are debating about is to 
 be deprecated, see 
 https://dlang.org/spec/legacy.html#alias-instance-member.
Well, first it should be deprecated,
I did that first, Walter said it shouldn't be a deprecation: https://github.com/dlang/dmd/pull/15863#issuecomment-1902711081 The problem is that if someone understood what it actually does (alias a member of a type), then deprecating that will deprecate correct code. But I think the confusion justifies a deprecation. So it was made a next edition error. Possibly it could be a warning in the current edition with -w. I did refine the error so it only happens for members of an instance that need `this` - https://github.com/dlang/dmd/pull/16813, merged yesterday.
Aug 28
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 8/25/24 19:27, Manu wrote:
 There's fault lines and fractures all over the place; this category of 
 issues should be addressed with a laser focus and ruthless murder... and 
 it should have happened 15 years ago.
FWIW with my frontend this just works: ```d struct S{ int x; } void foo(alias a)(){ a=2; } int bar(){ S s; foo!(s.x)(); return s.x; } static assert(bar()==2); ```
Aug 25
next sibling parent Manu <turkeyman gmail.com> writes:
On Mon, 26 Aug 2024, 05:46 Timon Gehr via Digitalmars-d, <
digitalmars-d puremagic.com> wrote:

 On 8/25/24 19:27, Manu wrote:
 There's fault lines and fractures all over the place; this category of
 issues should be addressed with a laser focus and ruthless murder... and
 it should have happened 15 years ago.
FWIW with my frontend this just works: ```d struct S{ int x; } void foo(alias a)(){ a=2; } int bar(){ S s; foo!(s.x)(); return s.x; } static assert(bar()==2); ```
Strap your fork to a CI machine and I'll use it exclusively! :) Or, you know, make a PR.

Aug 25
prev sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Sunday, 25 August 2024 at 19:40:48 UTC, Timon Gehr wrote:
 FWIW with my frontend this just works:
I've always wished there'd be a way for a nested struct to access its parent context. Can your frontend handle something like this: ``` struct S2(alias instance) { alias Outer = __traits(parent, instance); ref Outer outer() => *cast(Outer*)(cast(void*)&this - instance.offsetof); } struct S { S2!inner inner; } ``` ? There's a workaround using mixins, but it's not great: ``` mixin template S2(string name) { alias Outer = typeof(this); struct S2 { ref Outer outer() => *cast(Outer*)(cast(void*)&this - field.offsetof); void foo() { import std.stdio; writeln(name, ": outer.x = ", outer.x); } } mixin("S2 ", name, ";"); mixin("alias field = ", name, ";"); } struct S { int x; mixin S2!"inner"; } void main() { S s = S(42); s.inner.foo(); } ```
Aug 28
next sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 28 August 2024 at 16:37:12 UTC, Max Samukha wrote:
         ref Outer outer() => *cast(Outer*)(cast(void*)&this - 
 field.offsetof);
Looks like the name can be mixed-in directly: ``` ref Outer outer() => *cast(Outer*)(cast(void*)&this - mixin(name).offsetof); ```
Aug 28
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 8/28/24 18:37, Max Samukha wrote:
 On Sunday, 25 August 2024 at 19:40:48 UTC, Timon Gehr wrote:
 FWIW with my frontend this just works:
I've always wished there'd be a way for a nested struct to access its parent context. Can your frontend handle something like this: ...
Simplified example: ```d struct S(alias instance){} struct T{ S!instance instance; } ``` My frontend does not support this currently. It shouldn't be too hard to add support for this kind of thing though, as the general architecture of the code is set up to handle unusual analysis order. I am currently a bit too strapped on time to implement it, but will keep it in mind for when I possibly continue development on the frontend.
Sep 02
parent Max Samukha <maxsamukha gmail.com> writes:
On Monday, 2 September 2024 at 14:35:56 UTC, Timon Gehr wrote:

 My frontend does not support this currently. It shouldn't be 
 too hard to add support for this kind of thing though, as the 
 general architecture of the code is set up to handle unusual 
 analysis order. I am currently a bit too strapped on time to 
 implement it, but will keep it in mind for when I possibly 
 continue development on the frontend.
Understood, thanks.
Sep 03
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Sunday, 25 August 2024 at 05:07:43 UTC, Manu wrote:
 Like, from my example above, what even IS `s.tupleof`? It's 
 some kind of
 list of what kind of thing? Direct symbol references to members 
 of a live
 instance?
It's a symbol sequence of references to fields. ```d import std; struct S { int i; char c; } void main() { S s = {2, 'c'}; ref si = s.i; ref sc = s.c; alias tupleof = AliasSeq!(si, sc); // same as s.tupleof tupleof[0]++; s.writeln(); assert(s.i == 3); // this actually works alias a = tupleof[0]; a++; assert(s.i == 4); } ``` So `alias e = s.tupleof[0];` could be made to work. See also: https://dlang.org/spec/template.html#lvalue-sequences. BTW I'd like to make sequences a separate spec page from templates really.
 If s.tupleof can populate a list with that kind of thing, why 
 doesn't this
 work:

 struct S
 {
   int x, y;
 }

 struct T
 {
   S s;
   int i;

   alias a = i; // works
   alias b = s.x; // Doesn't work? Why?
 }
`a` is a symbol alias. `b` would be an expression if it did what you want. Instead it's the same as `S.x`, which needs an instance of S to use it at runtime. However, you could now use `ref b = s.x;` instead inside a method of T. ...
 alias b = s.tupleof[0]; // this emits a surprising error 
 message:

 error : alias `b` cannot alias an expression `AliasSeq!(s.x, 
 s.y)[0]`
 So, that 'list' I mention; does this error message imply that 
 this list given by `tupleof` is an AliasSeq? What exactly IS an 
 AliasSeq? What is the actual set of things that it can hold?
Symbols (declarations) and compile-time values. S.x is a declaration, s.x is a runtime value. `tupleof` is a symbol sequence of implicit ref declarations.
Aug 28
parent reply Manu <turkeyman gmail.com> writes:
On Wed, 28 Aug 2024 at 19:46, Nick Treleaven via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 25 August 2024 at 05:07:43 UTC, Manu wrote:
 Like, from my example above, what even IS `s.tupleof`? It's
 some kind of
 list of what kind of thing? Direct symbol references to members
 of a live
 instance?
It's a symbol sequence of references to fields. ```d import std; struct S { int i; char c; } void main() { S s = {2, 'c'}; ref si = s.i; ref sc = s.c; alias tupleof = AliasSeq!(si, sc); // same as s.tupleof tupleof[0]++; s.writeln(); assert(s.i == 3); // this actually works alias a = tupleof[0]; a++; assert(s.i == 4); } ``` So `alias e = s.tupleof[0];` could be made to work. See also: https://dlang.org/spec/template.html#lvalue-sequences. BTW I'd like to make sequences a separate spec page from templates really.
 If s.tupleof can populate a list with that kind of thing, why
 doesn't this
 work:

 struct S
 {
   int x, y;
 }

 struct T
 {
   S s;
   int i;

   alias a = i; // works
   alias b = s.x; // Doesn't work? Why?
 }
`a` is a symbol alias. `b` would be an expression if it did what you want. Instead it's the same as `S.x`, which needs an instance of S to use it at runtime.
Not necessarily; it doesn't need to carry around the expression; it could evaluate the resolve the expression on the spot.
 alias b = s.tupleof[0]; // this emits a surprising error
 message:

 error : alias `b` cannot alias an expression `AliasSeq!(s.x,
 s.y)[0]`
 So, that 'list' I mention; does this error message imply that
 this list given by `tupleof` is an AliasSeq? What exactly IS an
 AliasSeq? What is the actual set of things that it can hold?
Symbols (declarations) and compile-time values. S.x is a declaration, s.x is a runtime value. `tupleof` is a symbol sequence of implicit ref declarations.
What's a 'ref'?
Aug 28
parent reply Nick Treleaven <nick geany.org> writes:
On Wednesday, 28 August 2024 at 10:41:25 UTC, Manu wrote:
 On Wed, 28 Aug 2024 at 19:46, Nick Treleaven via Digitalmars-d 
 < digitalmars-d puremagic.com> wrote:
 struct T
 {
   S s;
   int i;

   alias a = i; // works
   alias b = s.x; // Doesn't work? Why?
 }
`a` is a symbol alias. `b` would be an expression if it did what you want. Instead it's the same as `S.x`, which needs an instance of S to use it at runtime.
Not necessarily; it doesn't need to carry around the expression; it could evaluate the resolve the expression on the spot.
It resolves to the field declaration `x`, which knows nothing about `s` - because `s.x` is not a declaration. It might confuse the concept of aliases if you allow them to refer to some sub-part of a declaration. You could instead write: ```d ref b() => s.x; ```
 `tupleof` is a symbol sequence of implicit ref declarations.
What's a 'ref'?
https://dlang.org/changelog/pending.html#dmd.reflocal
Aug 28
parent reply Manu <turkeyman gmail.com> writes:
Wed, 28 Aug 2024 at 21:16, Nick Treleaven via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Wednesday, 28 August 2024 at 10:41:25 UTC, Manu wrote:
 On Wed, 28 Aug 2024 at 19:46, Nick Treleaven via Digitalmars-d
 < digitalmars-d puremagic.com> wrote:
 struct T
 {
   S s;
   int i;

   alias a = i; // works
   alias b = s.x; // Doesn't work? Why?
 }
`a` is a symbol alias. `b` would be an expression if it did what you want. Instead it's the same as `S.x`, which needs an instance of S to use it at runtime.
Not necessarily; it doesn't need to carry around the expression; it could evaluate the resolve the expression on the spot.
It resolves to the field declaration `x`, which knows nothing about `s` - because `s.x` is not a declaration.
Right... that's that bug. And needs to be fixed. It might confuse
 the concept of aliases if you allow them to refer to some
 sub-part of a declaration.
Definitely no; it will distinctly UN-confuse the concept of aliases. It's been requested endlessly since forever, it's obviously how people expect it to work. Everyone I've introduced D to has found themself here in the first few days, and it just messes everything up. The wonky edge cases and work-arounds are a clear sign it's all gone off the rails. You could instead write:
 ```d
 ref b() => s.x;
 ```
Not the same thing at all... it's also an admission of defeat, and makes D look broken. The path of exploration that leads to this hack is a really bad experience, and it does not do us any favours in terms of optics, or language satisfaction.
 `tupleof` is a symbol sequence of implicit ref declarations.

 What's a 'ref'?
https://dlang.org/changelog/pending.html#dmd.reflocal
Yeah, I can't wait for the next release to land; we've been waiting literally forever for this! That said, it doesn't really answer my question; what IS a ref? Nobody really knows; it's not really a thing that the language can properly express. For instance, the evidence here: __traits(getParamterStorafeClasses, function, paramterByIntegerIndex) How would you expect to detect if something is ref, or scope, or whatever? Of course, what you expect is a STRING LITERAL, which you can compare to a string of the name of the storage class. There's no stronger evidence that storage classes are themselves such a broken idea that exist way outside of the language than passing around string literals to tell you a fact about some declaration. C++ puts these things in the type, and while that creates some awkward cases, it's infinitely better than what we have in D in terms of expressiveness and flexibility in terms of meta programming. Ref as part of a type means it can participate in type-like expressions, inferences, etc. What's kinda funny, is that your link to the cool ref-local feature (finally!) above will be shortly followed with "how do I detect if a local is a reference?" ... there's no __traits(getLocalVariableStorageClass, ...) So I still don't really know; what IS a ref? It's astonishing that s.tupleof is a sequence of ref's as you say... does anything else in the language have a semantic like that? How could I synthesise something like that from anything else if I wanted to?
Aug 28
parent reply Nick Treleaven <nick geany.org> writes:
On Wednesday, 28 August 2024 at 11:47:12 UTC, Manu wrote:
 For instance, the evidence here: 
 __traits(getParamterStorafeClasses,
 function, paramterByIntegerIndex)
 How would you expect to detect if something is ref, or scope, 
 or whatever?
__traits(isRef, x) I expect a trait for isScope could be added if needed.
 Of course, what you expect is a STRING LITERAL, which you can 
 compare to a
 string of the name of the storage class.
 There's no stronger evidence that storage classes are 
 themselves such a
 broken idea that exist way outside of the language than passing
Just because you can't e.g. alias a storage class doesn't mean it is 'outside' the language. It's part of a declaration.
 around
 string literals to tell you a fact about some declaration.
 C++ puts these things in the type, and while that creates some 
 awkward
 cases, it's infinitely better than what we have in D in terms of
 expressiveness and flexibility in terms of meta programming.
I've heard that C++ references are a complete swamp of special cases (regardless of lvalue vs rvalue reference).
 Ref as part of
 a type means it can participate in type-like expressions, 
 inferences, etc.
I think its better to explicitly write `ref` if you want a ref, rather than infer it.
 What's kinda funny, is that your link to the cool ref-local 
 feature (finally!) above will be shortly followed with "how do 
 I detect if a local is a reference?" ... there's no 
 __traits(getLocalVariableStorageClass, ...)
__traits(isRef, x) Example with `auto ref` in the changelog.
 So I still don't really know; what IS a ref?
It's a pointer that is automatically dereferenced on use, and never does pointer arithmetic.
 It's astonishing that s.tupleof is a sequence of ref's as you 
 say...
BTW that was just how I understand `.tupleof`. I see it as (a superset of) a sequence of implicit ref declarations.
 does anything else in the language have a semantic like that?
 How could I synthesise something like that from anything else 
 if I wanted to?
If you mean synthesize `tupleof`, I already showed how (without introspection support), the first example here: https://forum.dlang.org/post/fctetiyhbiyhadlmcyzr forum.dlang.org That example literally works with dmd recent git.
Aug 28
next sibling parent reply Manu <turkeyman gmail.com> writes:
On Thu, 29 Aug 2024 at 01:21, Nick Treleaven via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Wednesday, 28 August 2024 at 11:47:12 UTC, Manu wrote:
 For instance, the evidence here:
 __traits(getParamterStorafeClasses,
 function, paramterByIntegerIndex)
 How would you expect to detect if something is ref, or scope,
 or whatever?
__traits(isRef, x) I expect a trait for isScope could be added if needed.
Did you miss my point? The language can't *express *these things... we need backdoor information to hold the concept in any sort of expression.
 Of course, what you expect is a STRING LITERAL, which you can
 compare to a
 string of the name of the storage class.
 There's no stronger evidence that storage classes are
 themselves such a
 broken idea that exist way outside of the language than passing
Just because you can't e.g. alias a storage class doesn't mean it is 'outside' the language. It's part of a declaration.
You didn't miss my point. Hmmm.
 around
 string literals to tell you a fact about some declaration.
 C++ puts these things in the type, and while that creates some
 awkward
 cases, it's infinitely better than what we have in D in terms of
 expressiveness and flexibility in terms of meta programming.
I've heard that C++ references are a complete swamp of special cases (regardless of lvalue vs rvalue reference).
You've "heard"? I'm sorry, but your qualification to comment on the topic is definitely problematic from here on... Anyone who holds the opinion that C++ references are a swamp of special cases *by contrast *has clearly not had any comparable experience with D references (and additional *suite* of storage classes). Nobody with experience in this matter can honestly say with a straight face that C++ is complicated and edgy by direct comparison. Nothing in D is more awkward or poorly expressed.
 What's kinda funny, is that your link to the cool ref-local
 feature (finally!) above will be shortly followed with "how do
 I detect if a local is a reference?" ... there's no
 __traits(getLocalVariableStorageClass, ...)
__traits(isRef, x) Example with `auto ref` in the changelog.
Okay, fair; I had my mind on the general query relating to storage class like the one that returns a list of strings for each parameter. But it's like you say "one could be added for scope"; which actually demonstrates my point equally well. ... and why do we have 2 ways that do exactly the same thing? C++ just doesn't have any of this nonsense. My biggest sense of loss from C++ to D is this fundamental area of the language in D that exists outside the language, and requires hacks and general weird-shit to access.
 So I still don't really know; what IS a ref?

 It's a pointer that is automatically dereferenced on use, and
 never does pointer arithmetic.
No, that's what it *does*. Write me an expression that embodies the concept? Write me an expression that copies ref-ness from one declaration to another declaration, for instance; I might be synthesising a parameter list for a shim with information from a given function... It can't be expressed in the language. It's just an internal compiler concept that's unbelievably awkward to reason about, and can only be reasoned with back-door information. Have you had a look at core.lifetime recently? Take a look at C++'s implementation of `std::forward`, `std:: move`, `emplace` (aka placement new)... tell me the situation in D is superior... core.lifetime is a war zone; you'll get a really good signal of just how far off the mark we have landed when comparing those fundamental language primitives. There's basically nothing lower in the concept stack than core.lifetime; so why is it a complete mess? The reason is because none of our core concepts fit together; D is made out of parts with seriously jagged edges, and it needs a flood of hacky special-case reasoning to resolve the problems at the lowest level. D's advantage is that a lot of things ARE POSSIBLE, but they come at a massive intellectual cost, and it doesn't need to be that way. It *shouldn't* be that way.
 It's astonishing that s.tupleof is a sequence of ref's as you
 say...
BTW that was just how I understand `.tupleof`. I see it as (a superset of) a sequence of implicit ref declarations.
Okay, so you might be wrong? Whether you are or aren't is irrelevant though, this is further evidence of the problem... it's not a "reasonable" design in fundamental terms. It's actually quite literally anti-reasonable. It's just internal compiler magic; the whole thing is a big special case, which creates edge cases at almost every single point of contact. If you need a __traits to know a fundamental primitive fact like ref, something already went wrong.
 does anything else in the language have a semantic like that?
 How could I synthesise something like that from anything else
 if I wanted to?
If you mean synthesize `tupleof`, I already showed how (without introspection support), the first example here: https://forum.dlang.org/post/fctetiyhbiyhadlmcyzr forum.dlang.org That example literally works with dmd recent git.
I'm very keen to play with ref locals when it lands; it's been such a long time coming. That's not quite the same thing though; you've declared 2 local variables; does that infer they allocate stack space? Do I rely on the optimiser now to remove them? It looks like yet-another-workaround/hack to me.
Aug 28
next sibling parent Nick Treleaven <nick geany.org> writes:
On Thursday, 29 August 2024 at 02:29:21 UTC, Manu wrote:
 I've heard that C++ references are a complete swamp of special 
 cases (regardless of lvalue vs rvalue reference).
You've "heard"? I'm sorry, but your qualification to comment on the topic is definitely problematic from here on...
Perhaps you'd like to see what someone who wrote a C++ compiler thinks:
 You might also consider the "uniformity" of the ref type in 
 C++. It's awful - it's a special case EVERYWHERE in the C++ 
 type system! It just does not fit as a type qualifier.
https://forum.dlang.org/post/m60oa4$kd5$1 digitalmars.com
Aug 30
prev sibling next sibling parent Nick Treleaven <nick geany.org> writes:
On Thursday, 29 August 2024 at 02:29:21 UTC, Manu wrote:
 I've heard that C++ references are a complete swamp of special 
 cases (regardless of lvalue vs rvalue reference).
You've "heard"? I'm sorry, but your qualification to comment on the topic is definitely problematic from here on...
Herb Sutter:
 References are for parameter passing, including range-for. 
 Sometimes they’re useful as local variables
https://herbsutter.com/2020/02/23/references-simply/ And in Herb's C++2 project, references are not part of the type. There is `inout`, which is a parameter storage class, like D's `ref`, and like all modern languages I can think of.
Aug 30
prev sibling parent Nick Treleaven <nick geany.org> writes:
On Thursday, 29 August 2024 at 02:29:21 UTC, Manu wrote:
 Did you miss my point? The language can't *express *these 
 things... we need backdoor information to hold the concept in 
 any sort of expression.
Being able to compose attributes would be useful, yes. I'm not sure how important having that is though.
 BTW that was just how I understand `.tupleof`. I see it as (a 
 superset of) a sequence of implicit ref declarations.
Okay, so you might be wrong?
Yes, sorry. See Timon's reply to me.
 If you mean synthesize `tupleof`, I already showed how 
 (without introspection support), the first example here: 
 https://forum.dlang.org/post/fctetiyhbiyhadlmcyzr forum.dlang.org

 That example literally works with dmd recent git.
I'm very keen to play with ref locals when it lands; it's been such a long time coming. That's not quite the same thing though; you've declared 2 local variables; does that infer they allocate stack space? Do I rely on the optimiser now to remove them? It looks like yet-another-workaround/hack to me.
Well if .tupleof didn't exist and I didn't have write access to the source aggregate type (or I wanted it on a static array), then I could model it with a mixin that expands to my local ref declaration sequence alias. But yes that might well be less efficient.
Aug 31
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 8/28/24 17:19, Nick Treleaven wrote:
 It's astonishing that s.tupleof is a sequence of ref's as you say...
BTW that was just how I understand `.tupleof`. I see it as (a superset of) a sequence of implicit ref declarations.
Well, but that is not what it is. ```d alias Seq(T...)=T; struct S{ int x; alias expand=Seq!x; } void main(){ S s; pragma(msg,__traits(isRef,s.tupleof[0])); // false pragma(msg,__traits(isSame,s.expand,s.tupleof)); // true } ```
Aug 30
parent reply Nick Treleaven <nick geany.org> writes:
On Saturday, 31 August 2024 at 06:45:00 UTC, Timon Gehr wrote:
 On 8/28/24 17:19, Nick Treleaven wrote:
 It's astonishing that s.tupleof is a sequence of ref's as you 
 say...
BTW that was just how I understand `.tupleof`. I see it as (a superset of) a sequence of implicit ref declarations.
Well, but that is not what it is. ```d alias Seq(T...)=T; struct S{ int x; alias expand=Seq!x; } void main(){ S s; pragma(msg,__traits(isRef,s.tupleof[0])); // false pragma(msg,__traits(isSame,s.expand,s.tupleof)); // true } ```
OK, thanks. And `s.expand[0].writeln();` works too. So the following error makes sense: alias x = s.expand[0]; x.writeln(); // Error: accessing non-static variable `x` requires an instance of `S`
Aug 31
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 8/31/24 11:23, Nick Treleaven wrote:
 
 So the following error makes sense:
 
      alias x = s.expand[0];
      x.writeln(); // Error: accessing non-static variable `x` requires 
 an instance of `S`
It would be consistent, but it does not make sense.
Aug 31
parent reply Nick Treleaven <nick geany.org> writes:
On Saturday, 31 August 2024 at 12:43:53 UTC, Timon Gehr wrote:
 On 8/31/24 11:23, Nick Treleaven wrote:
 
 So the following error makes sense:
 
      alias x = s.expand[0];
      x.writeln(); // Error: accessing non-static variable `x` 
 requires an instance of `S`
It would be consistent, but it does not make sense.
Why not?
Sep 02
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 9/2/24 11:53, Nick Treleaven wrote:
 On Saturday, 31 August 2024 at 12:43:53 UTC, Timon Gehr wrote:
 On 8/31/24 11:23, Nick Treleaven wrote:
 So the following error makes sense:

      alias x = s.expand[0];
      x.writeln(); // Error: accessing non-static variable `x` 
 requires an instance of `S`
It would be consistent, but it does not make sense.
Why not?
Because it does not just work. The thing it is consistent with does not make sense in the first place. What do we gain from this not working?
Sep 02
prev sibling parent reply Manu <turkeyman gmail.com> writes:
Here's another one just now:

return __traits(getMember, instance, funName)(args);   // this works as it
should


alias fun =3D __traits(getMember, instance, funName);
return fun(args);   // error : calling non-static function `myFun` requires
an instance of type `T`


Again... this isn't acceptable in 2024. No 'explanation' should be
acceptable to any sound mind. It's a critical bug, and it should have been
fixed 15-20 years ago.

On Sun, 25 Aug 2024 at 15:07, Manu <turkeyman gmail.com> wrote:

 On Sun, 25 Aug 2024 at 04:56, ryuukk_ via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:

 On Saturday, 24 August 2024 at 17:56:21 UTC, monkyyy wrote:
 On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:
 alias x =3D s.tupleof; // this works
 alias y =3D s.tupleof[0]; // this is a compile error?!

 How can embarrassing edge cases like this still exist in the
 language today? I'm just reacquainting myself with all the
 reasons that I've had such a hard time trying to convince my
 colleagues to take D seriously for such a long time.

 =F0=9F=98=AB
```d auto tuple(T...)(T args){ struct Tuple{ enum istuple=3Dtrue; T me; alias me this; } return Tuple(args); } unittest{ auto foo=3Dtuple(1,"hi"); assert(foo[0]=3D=3D1); assert(foo[1]=3D=3D"hi"); auto bar=3Dtuple(); } auto totuple(T)(T a) if(is(typeof(a.istuple)))=3D>a; auto totuple(T)(T a) if( ! is(typeof(a.istuple)))=3D>tuple(a); auto maybetuple(T...)(T a){ static if(T.length=3D=3D1){ return a[0]; } else { return tuple(a); }} ``` Could be fixed with a better std.meta
D needs native tuple, not this mess
Facts. This is a really old drum to beat on... but maybe we need to start pounding it again. It's not strictly this simple though; I think there's a lot of work up-front. We don't really even know what a tuple is, or even what "kinds" of things the language can express... Like, there's more than types and values. There's symbol aliases, which may or may not carry an instance reference with them, declaration aliases=
,
 which may carry names and properties like storage class, there's sometime=
s
 expression aliases, there's potentially attributes, and heaps of other
 stuff that exists outside the language; like storage class, which doesn't
 seem to have any presence in the language at all; it's queried with a
 __traits and comically tells you those facts as string literals! I think
 this space might be the heart and soul of D's foundational issues, and as
 such, it's excruciatingly hard to make corrections.

 Like, from my example above, what even IS `s.tupleof`? It's some kind of
 list of what kind of thing? Direct symbol references to members of a live
 instance?
 If s.tupleof can populate a list with that kind of thing, why doesn't thi=
s
 work:

 struct S
 {
   int x, y;
 }

 struct T
 {
   S s;
   int i;

   alias a =3D i; // works
   alias b =3D s.x; // Doesn't work? Why?
 }

 It seems like s.tupleof presents that there are semantics in the language
 to express this sort of thing, but it's not clear what to call that.

 Likewise in my example above:

 alias a =3D s.tupleof; // this can hold the list of references, which see=
m
 to carry around their instance reference with them
 alias b =3D s.tupleof[0]; // this emits a surprising error message:

 error : alias `b` cannot alias an expression `AliasSeq!(s.x, s.y)[0]`

 So, that 'list' I mention; does this error message imply that this list
 given by `tupleof` is an AliasSeq? What exactly IS an AliasSeq? What is t=
he
 actual set of things that it can hold?

 If tupleof is an AliasSeq, then what's going on here:

 alias c =3D AliasSeq!(s.tupleof);
 alias d =3D c[0]; // the error is now gone??


 I think a good indication that this whole space is profoundly troubled
 when classic patterns like this emerge:

 template T(alias X) { use X }   // oh no you don't, alias is very
 opinionated! you'll need this instead:
 template T(X...) if (X.length =3D=3D 1) { use X[0] }

 Who here can honestly say they thought that was a reasonable thing to
 write the first time they encountered that piece of comedy gold?
 ... and why are they even different things? If an AliasSeq isn't a
 sequence of aliases, what is it? What are people supposed to imagine it i=
s?
 These are rhetorical questions, put yourself in an outside perspective; I
 know you can 'explain' it. I used to be able to explain it, but it turns
 out that with a few years off from D that toxicity in my mind seems to ha=
ve
 subsided to some degree! I'm reacquainting myself with a sea of nonsense
 that I kinda just settled into with sufficient sustained exposure.

 No matter how you look at it though, this shouldn't be a valid forum post
 in 2024...
Aug 24
next sibling parent reply Dom DiSc <dominikus scherkl.de> writes:
On Sunday, 25 August 2024 at 06:59:11 UTC, Manu wrote:
 Here's another one just now:

 return __traits(getMember, instance, funName)(args);   // this 
 works as it
 should


 alias fun = __traits(getMember, instance, funName);
 return fun(args);   // error : calling non-static function 
 `myFun` requires
 an instance of type `T`
Funny error message. Where does myFun and T come from?
Aug 25
parent reply Manu <turkeyman gmail.com> writes:
On Sun, 25 Aug 2024 at 19:11, Dom DiSc via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 25 August 2024 at 06:59:11 UTC, Manu wrote:
 Here's another one just now:

 return __traits(getMember, instance, funName)(args);   // this
 works as it
 should


 alias fun = __traits(getMember, instance, funName);
 return fun(args);   // error : calling non-static function
 `myFun` requires
 an instance of type `T`
Funny error message. Where does myFun and T come from?
struct T { void myFun(int) {} } T instance; enum funName = "myFun";
Aug 25
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Please post complete examples of the cases, instead of just the line with the 
error message. The missing lines are critical to understanding the bug report.
Aug 25
next sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Monday, 26 August 2024 at 05:25:00 UTC, Walter Bright wrote:
 Please post complete examples of the cases, instead of just the 
 line with the error message. The missing lines are critical to 
 understanding the bug report.
I must be trolling.
Aug 25
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Monday, 26 August 2024 at 05:25:00 UTC, Walter Bright wrote:
 Please post complete examples of the cases, instead of just the 
 line with the error message. The missing lines are critical to 
 understanding the bug report.
```d struct T { void myFun(int) {} } T instance; enum funName = "myFun"; void main() { int args = 0; alias fun = __traits(getMember, instance, funName); return fun(args); // error : calling non-static function `myFun` requires an instance of type `T` } ``` -Steve
Aug 27
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Thank you. Anyone want to post it to https:issues.dlang.org ?
Sep 03
parent reply Nick Treleaven <nick geany.org> writes:
On Wednesday, 4 September 2024 at 00:32:02 UTC, Walter Bright 
wrote:
 Thank you. Anyone want to post it to https:issues.dlang.org ?
Manu already filed it, see: https://issues.dlang.org/show_bug.cgi?id=24720
Sep 04
parent Walter Bright <newshound2 digitalmars.com> writes:
good!
Sep 09
prev sibling next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
Related issue we've had in the recent year:

https://issues.dlang.org/show_bug.cgi?id=23500

https://issues.dlang.org/show_bug.cgi?id=23761

I thought it was resolved, but perhaps not.
Aug 25
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/24/2024 11:59 PM, Manu wrote:
 Here's another one just now:
 
 return __traits(getMember, instance, funName)(args);   // this works as it
should
 
 
 alias fun = __traits(getMember, instance, funName);
 return fun(args);   // error : calling non-static function `myFun` requires
an 
 instance of type `T`
 
 
 Again... this isn't acceptable in 2024. No 'explanation' should be acceptable
to 
 any sound mind. It's a critical bug, and it should have been fixed 15-20 years
ago.
Thank you for posting this, but it is an incomplete example. Please don't make me guess what is missing - it's a big time saver if you provide it.
Aug 25
prev sibling next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!

 How can embarrassing edge cases like this still exist in the 
 language today? I'm just reacquainting myself with all the 
 reasons that I've had such a hard time trying to convince my 
 colleagues to take D seriously for such a long time.

 😫
I am going to fix this if it's not fixed by next week. I feel like going back to this.
Aug 24
parent user1234 <user1234 12.de> writes:
On Saturday, 24 August 2024 at 18:31:21 UTC, Stefan Koch wrote:
 On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!

 How can embarrassing edge cases like this still exist in the 
 language today? I'm just reacquainting myself with all the 
 reasons that I've had such a hard time trying to convince my 
 colleagues to take D seriously for such a long time.

 😫
I am going to fix this if it's not fixed by next week. I feel like going back to this.
The feature might be covered in this old PR (https://github.com/dlang/dmd/pull/11273/files). However it covered a wider scope.
Aug 24
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/24/2024 9:36 AM, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!
Can you please repost with the missing declarations from your example? Thanks!
Aug 25
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 8/26/24 07:21, Walter Bright wrote:
 On 8/24/2024 9:36 AM, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!
Can you please repost with the missing declarations from your example? Thanks!
This suffices to reproduce: ```d struct S{ int x; } S s; alias x = s.tupleof; // this works alias y = s.tupleof[0]; // this is a compile error?! ``` The underlying issue is that `.tupleof` has some magic that is not accessible to aliases. Consider: ```d struct S{ int x; } void main(){ S s; alias x = s.tupleof; x[0] = 2; // ok alias y = s.x; y = 2; // error } ``` So `x[0]` is an alias to the field of an instance. I think all of these examples should just work. When template parameters get involved however, local instantiation can get a bit tricky. So making it work without breakage probably also comes down to the issue that local instantiation works with only one context, which had a fix in DMD but was never ported to GDC and LDC, and was then reverted via deprecation in DMD as well. This is one of the most annoying and long-standing issues in D.
Aug 26
next sibling parent Manu <turkeyman gmail.com> writes:
On Mon, 26 Aug 2024 at 18:45, Timon Gehr via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 8/26/24 07:21, Walter Bright wrote:
 On 8/24/2024 9:36 AM, Manu wrote:
 alias x = s.tupleof; // this works
 alias y = s.tupleof[0]; // this is a compile error?!
Can you please repost with the missing declarations from your example? Thanks!
This suffices to reproduce: ```d struct S{ int x; } S s; alias x = s.tupleof; // this works alias y = s.tupleof[0]; // this is a compile error?! ``` The underlying issue is that `.tupleof` has some magic that is not accessible to aliases. Consider: ```d struct S{ int x; } void main(){ S s; alias x = s.tupleof; x[0] = 2; // ok alias y = s.x; y = 2; // error } ``` So `x[0]` is an alias to the field of an instance. I think all of these examples should just work. When template parameters get involved however, local instantiation can get a bit tricky. So making it work without breakage probably also comes down to the issue that local instantiation works with only one context, which had a fix in DMD but was never ported to GDC and LDC, and was then reverted via deprecation in DMD as well. This is one of the most annoying and long-standing issues in D.
I endorse every word of this post.
Aug 26
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/26/2024 1:40 AM, Timon Gehr wrote:
 When template parameters get involved however, local instantiation can get a
bit 
 tricky. So making it work without breakage probably also comes down to the
issue 
 that local instantiation works with only one context, which had a fix in DMD
but 
 was never ported to GDC and LDC, and was then reverted via deprecation in DMD
as 
 well. This is one of the most annoying and long-standing issues in D.
Was that the multiple context pointer thing? Multiple inheritance again :-/
Aug 27