Bug 24717 – alias edge cases with tupleof

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2024-08-24T17:47:46Z
Last change time
2024-12-13T19:36:57Z
Assigned to
No Owner
Creator
Manu
Moved to GitHub: dmd#18265 →

Comments

Comment #0 by turkeyman — 2024-08-24T17:47:46Z
alias x = s.tupleof; // this works alias y = s.tupleof[0]; // this is a compile error?! It's long past time to fix this. alias has an overwhelming sea of edge cases. It's extremely off-putting to potential D users, because this category of meta is absolutely integral to why they try out the language at all.
Comment #1 by turkeyman — 2024-08-24T17:49:07Z
Also this: alias z = AliasSeq!(s.tupleof); // error, but it should be a no-op
Comment #2 by nick — 2024-08-28T11:24:11Z
> alias y = s.tupleof[0]; // this is a compile error?! Inside a function, `.tupleof` on a struct/static array instance should be implemented as a symbol sequence of implicit ref declarations: 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); // should be the same as s.tupleof alias a = tupleof[0]; // works a++; assert(s.i == 3); alias z = AliasSeq!tupleof; // works assert(++z[0] == 4); } > alias z = AliasSeq!(s.tupleof); // error, but it should be a no-op That line doesn't error, but using z does: z[0].writeln(); // Error: accessing non-static variable `x` requires an instance of `S`
Comment #3 by nick — 2024-08-28T14:54:01Z
> should be implemented as a symbol sequence of implicit ref declarations Actually `AliasSeq!(__si, __sc)` can't be the lowering because then `__traits(identifier, s.tupleof[0])` would be `__si`, not `i`. But conceptually it should be a superset of an lvalue sequence.
Comment #4 by nick — 2024-08-31T09:41:20Z
> alias y = s.tupleof[0]; // this is a compile error?! The error is: Error: alias `y` cannot alias an expression `AliasSeq!(s.x)[0]` That is because an alias declaration cannot target a value. For: struct S { int x; alias expand=Seq!x; } Turns out .tupleof is actually equivalent to the `expand` alias, see: https://forum.dlang.org/post/[email protected] alias z = AliasSeq!(s.tupleof); z[0].writeln(); // Error: accessing non-static variable `x` requires an instance of `S` So the above error is consistent with the design of symbol aliases. Changing this issue to an enhancement.
Comment #5 by nick — 2024-08-31T09:46:21Z
> That is because an alias declaration cannot target a value. Sorry, s.x can be aliased as a symbol. alias y = s.tupleof[0]; // error alias x = s.x; // OK x.writeln; // error, no instance of S - correct by design So there is a bug, the `y` alias should work like `x`.
Comment #6 by turkeyman — 2024-08-31T22:57:25Z
I just want to be clear again; it's definitely not "correct by design", it is absolutely, and proven time and time again over decades INCORRECT by design, and this just needs to be fixed. The expression is expected to work by everyone who approaches it, and it should work.
Comment #7 by maxsamukha — 2024-09-01T09:23:39Z
(In reply to Manu from comment #6) > decades INCORRECT by design Not incorrect, but buggy and definitely not what most people expect.
Comment #8 by turkeyman — 2024-09-01T11:49:18Z
Nar, 'incorrect' is the only possible description, and I will die on this hill. "Most people" is an understatement ;) 'Explaining' things at the expense of reality is a physiological trap that our kind fall into very easily. This particular thing has gone on for way way too long, and it's time we put it to bed.
Comment #9 by turkeyman — 2024-09-01T11:50:40Z
**psychological trap... bloody autocorrect!
Comment #10 by maxsamukha — 2024-09-01T13:08:13Z
(In reply to Manu from comment #8) > Nar, 'incorrect' is the only possible description, and I will die on this > hill. > "Most people" is an understatement ;) > > 'Explaining' things at the expense of reality is a physiological trap that > our kind fall into very easily. > This particular thing has gone on for way way too long, and it's time we put > it to bed. Anyway, if you guys are going to "fix" that, please make sure that there is still a way to get a "contextless" reference to a member, that is, (an alternative of) this still works: void apply(alias foo)(ref S s) { assert (__traits(child, s, foo) == 1); int delegate() dg; dg.ptr = &s; dg.funcptr = &foo; assert(dg() == 1); } struct S { int x; int foo() => x; } void main() { S s = S(1); apply!(S.foo)(s); }
Comment #11 by turkeyman — 2024-09-01T13:12:51Z
Yeah it's fine, just alias a member of the type rather than the instance. You can typeof(instance) of you want to use instance as the point of reference.
Comment #12 by maxsamukha — 2024-09-01T13:57:30Z
(In reply to Manu from comment #11) > Yeah it's fine, just alias a member of the type rather than the instance. > You can typeof(instance) of you want to use instance as the point of > reference. There are also cases where the explicitly specified static context is ignored, as in: struct S { void foo() { pragma(msg, typeof(&S.foo)); // void delegate(); auto f = &S.foo; pragma(msg, typeof(f)); // void delegate(); } pragma(msg, typeof(&S.foo)); // void function(); } It'd be nice to see them fixed too.
Comment #13 by turkeyman — 2024-09-01T23:12:55Z
Ah yes, good point. I also had an encounter with that exact surprise about 2 days ago aswell. I couldn't work out how to explain that... I just had to shake me head and move on.
Comment #14 by maxsamukha — 2024-09-02T05:32:12Z
(In reply to Manu from comment #13) > Ah yes, good point. I also had an encounter with that exact surprise about 2 > days ago aswell. > I couldn't work out how to explain that... I just had to shake me head and > move on. The same logic as that of alias - the reference is resolved to a contextless symbol, and then the implicit 'this' is used as the context. struct S { int x; void foo() { alias y = S.x; auto z = y; // `z` is resolved to `this.x`; } } (Disclaimer: I'm not defending the "symbol" nonsense).
Comment #15 by maxsamukha — 2024-09-02T05:48:41Z
(In reply to Max Samukha from comment #14) > auto z = y; // `z` is resolved to `this.x`; `y`, not `z`;
Comment #16 by robert.schadek — 2024-12-13T19:36:57Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18265 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB