digitalmars.D - This needs to be fixed
- Manu (8/8) Aug 24 alias x =3D s.tupleof; // this works
- monkyyy (25/32) Aug 24 ```d
- ryuukk_ (2/36) Aug 24 D needs native tuple, not this mess
- Manu (63/101) Aug 24 Facts.
- Steven Schveighoffer (23/84) Aug 25 All good points I think. AliasSeq and aliases in general have
- monkyyy (5/7) Aug 25 Hard no, overload sets and auto flattening are super magic and
- Manu (24/105) Aug 25 Indeed, and despite that, it's also quite likely that it is simultaneous...
- monkyyy (41/46) Aug 25 I believe its a struct offset
- user1234 (8/22) Aug 25 Just in case, the kind of alias you are debating about is to be
- Timon Gehr (3/6) Aug 25 Well, first it should be deprecated, then at some point it should just
- Nick Treleaven (11/17) Aug 28 I did that first, Walter said it shouldn't be a deprecation:
- Timon Gehr (12/15) Aug 25 FWIW with my frontend this just works:
- Manu (4/19) Aug 25 Strap your fork to a CI machine and I'll use it exclusively! :)
- Max Samukha (45/46) Aug 28 I've always wished there'd be a way for a nested struct to access
- Max Samukha (6/8) Aug 28 Looks like the name can be mixed-in directly:
- Timon Gehr (13/22) Sep 02 Simplified example:
- Max Samukha (2/8) Sep 03 Understood, thanks.
- Nick Treleaven (37/63) Aug 28 It's a symbol sequence of references to fields.
- Manu (5/69) Aug 28 Not necessarily; it doesn't need to carry around the expression; it coul...
- Nick Treleaven (10/31) Aug 28 It resolves to the field declaration `x`, which knows nothing
- Manu (41/73) Aug 28 Right... that's that bug. And needs to be fixed.
- Nick Treleaven (19/49) Aug 28 __traits(isRef, x)
- Manu (53/97) Aug 28 Did you miss my point? The language can't *express *these things... we n...
- Nick Treleaven (4/12) Aug 30 Perhaps you'd like to see what someone who wrote a C++ compiler
- Nick Treleaven (6/13) Aug 30 https://herbsutter.com/2020/02/23/references-simply/
- Nick Treleaven (9/30) Aug 31 Being able to compose attributes would be useful, yes. I'm not
- Timon Gehr (14/18) Aug 30 Well, but that is not what it is.
- Nick Treleaven (6/25) Aug 31 OK, thanks. And `s.expand[0].writeln();` works too.
- Timon Gehr (2/8) Aug 31 It would be consistent, but it does not make sense.
- Nick Treleaven (2/10) Sep 02 Why not?
- Timon Gehr (3/15) Sep 02 Because it does not just work. The thing it is consistent with does not
- Manu (17/119) Aug 24 Here's another one just now:
- Dom DiSc (2/10) Aug 25 Funny error message. Where does myFun and T come from?
- Manu (8/21) Aug 25 struct T
- Walter Bright (2/2) Aug 25 Please post complete examples of the cases, instead of just the line wit...
- Max Samukha (2/5) Aug 25 I must be trolling.
- Steven Schveighoffer (17/20) Aug 27 ```d
- Walter Bright (1/1) Sep 03 Thank you. Anyone want to post it to https:issues.dlang.org ?
- Nick Treleaven (4/5) Sep 04 Manu already filed it, see:
- Walter Bright (1/1) Sep 09 good!
- Richard (Rikki) Andrew Cattermole (4/4) Aug 25 Related issue we've had in the recent year:
- Walter Bright (3/15) Aug 25 Thank you for posting this, but it is an incomplete example. Please don'...
- Stefan Koch (3/10) Aug 24 I am going to fix this if it's not fixed by next week.
- user1234 (4/16) Aug 24 The feature might be covered in this old PR
- Walter Bright (2/4) Aug 25 Can you please repost with the missing declarations from your example? T...
- Timon Gehr (29/36) Aug 26 This suffices to reproduce:
- Manu (3/39) Aug 26 I endorse every word of this post.
- Walter Bright (3/8) Aug 27 Was that the multiple context pointer thing?
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
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
On Saturday, 24 August 2024 at 17:56:21 UTC, monkyyy wrote:On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:D needs native tuple, not this messalias 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
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: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...On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:D needs native tuple, not this messalias 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
Aug 24
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
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
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: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.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 inOh 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.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 think a good indication that this whole space is profoundlyIt'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.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.
Aug 25
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
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
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
On Sunday, 25 August 2024 at 19:42:08 UTC, Timon Gehr wrote:On 8/25/24 21:35, user1234 wrote: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.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,
Aug 28
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
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:Strap your fork to a CI machine and I'll use it exclusively! :) Or, you know, make a PR.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
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
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
On 8/28/24 18:37, Max Samukha wrote:On Sunday, 25 August 2024 at 19:40:48 UTC, Timon Gehr wrote: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.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: ...
Sep 02
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
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
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:Not necessarily; it doesn't need to carry around the expression; it could evaluate the resolve the expression on the spot.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.What's a 'ref'?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
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: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; ```Not necessarily; it doesn't need to carry around the expression; it could evaluate the resolve the expression on the spot.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.https://dlang.org/changelog/pending.html#dmd.reflocal`tupleof` is a symbol sequence of implicit ref declarations.What's a 'ref'?
Aug 28
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:Right... that's that bug. And needs to be fixed. It might confuseOn Wed, 28 Aug 2024 at 19:46, Nick Treleaven via Digitalmars-d < digitalmars-d puremagic.com> wrote:It resolves to the field declaration `x`, which knows nothing about `s` - because `s.x` is not a declaration.Not necessarily; it doesn't need to carry around the expression; it could evaluate the resolve the expression on the spot.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.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.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?`tupleof` is a symbol sequence of implicit ref declarations.https://dlang.org/changelog/pending.html#dmd.reflocalWhat's a 'ref'?
Aug 28
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 passingJust 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
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: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.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 canYou didn't miss my point. Hmmm.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 passingJust because you can't e.g. alias a storage class doesn't mean it is 'outside' the language. It's part of a declaration.aroundYou'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.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).What's kinda funny, is that your link to the cool ref-localOkay, 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.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.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 youOkay, 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.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?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.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
On Thursday, 29 August 2024 at 02:29:21 UTC, Manu wrote:Perhaps you'd like to see what someone who wrote a C++ compiler thinks: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...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
On Thursday, 29 August 2024 at 02:29:21 UTC, Manu wrote:Herb Sutter: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...References are for parameter passing, including range-for. Sometimes they’re useful as local variableshttps://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
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.Yes, sorry. See Timon's reply to me.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?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.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 31
On 8/28/24 17:19, Nick Treleaven wrote: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 } ```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.
Aug 30
On Saturday, 31 August 2024 at 06:45:00 UTC, Timon Gehr wrote:On 8/28/24 17:19, Nick Treleaven wrote: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`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 } ```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.
Aug 31
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
On Saturday, 31 August 2024 at 12:43:53 UTC, Timon Gehr wrote:On 8/31/24 11:23, Nick Treleaven wrote:Why not?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.
Sep 02
On 9/2/24 11:53, Nick Treleaven wrote:On Saturday, 31 August 2024 at 12:43:53 UTC, Timon Gehr wrote: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?On 8/31/24 11:23, Nick Treleaven wrote:Why not?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.
Sep 02
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: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=On Saturday, 24 August 2024 at 16:36:17 UTC, Manu wrote:D needs native tuple, not this messalias 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.metawhich may carry names and properties like storage class, there's sometime=sexpression 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=swork: 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=mto 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=heactual 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=vesubsided 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
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
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:struct T { void myFun(int) {} } T instance; enum funName = "myFun";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
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
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
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
Thank you. Anyone want to post it to https:issues.dlang.org ?
Sep 03
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
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
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
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
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:The feature might be covered in this old PR (https://github.com/dlang/dmd/pull/11273/files). However it covered a wider scope.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
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
On 8/26/24 07:21, Walter Bright wrote:On 8/24/2024 9:36 AM, Manu wrote: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.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 26
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:I endorse every word of this post.On 8/24/2024 9:36 AM, Manu wrote: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.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 26
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