Bug 19615 – alias this not taken when member is

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-01-25T19:52:58Z
Last change time
2024-12-13T19:02:10Z
Assigned to
No Owner
Creator
Bolpat
Moved to GitHub: dmd#19532 →

Comments

Comment #0 by qs.il.paperinik — 2019-01-25T19:52:58Z
When a class/struct has alias-this and a (different) member is accessed, but accessing fails, e.g. the the member is a function (i.e. a method) with no overload viable with the given argument types, the alias-this member is not being tried. struct Test1 { // Note: No arguments int member() { return 0; } } struct Test2 { Test1 field; alias field this; // Note: One argument int member(int n) { return n; } } void main() { Test2 test; static assert(!__traits(compiles, { int i1 = test.member(); })); int i2 = test.field.member(); } Removing member from Test2 makes the static assert fail, i.e. the alias-this access valid. In this minimal example, it can be helped adding a trivial overload of member to Test2. This is not always viable, e.g. if the alias-this references something that cannot be returned by a function: An AliasSeq. struct Test(bool hasIndex, Types...) { Types fields; alias fields this; static if (hasIndex) { int[] opIndex() { return [ ]; } } } void main() { Test!(false, int) testF; int[] iF = testF[]; // fails: no opIndex (intended) testF[0] = 1; // ok: equivalent to `testF.fields[0] = 1` by alias this Test!(true, int) testT; int[] iT = testT[]; // ok: equivalent to `testT.opIndex()` testT[0] = 1; // fails: testT.opIndex not callable with one argument. } There is no way to have slice obj[] and type-safe access to the fields with obj[index] at the same time. This can be resolved, too, by letting the compiler not rewrite obj[0] to obj.opIndex(0) if the call does not compile.
Comment #1 by razvan.nitu1305 — 2019-01-28T13:15:06Z
I don't think this issue is valid. Alias this should be viewed as inheritance, so your example should behave exactly as: class Test1 { int member() { return 0; } } class Test2 : Test1 { int member(int n) { return n; } } void main() { Test2 a; a.member(); // error : function test.Test2.member(int n) is not callable using argument types () } Currently, in dmd if you want to include an overload in the baseclass overload set you have to use alias (alias member = typeof(super).member), then the example compiles. I suggest you use this technique in your code. I suggest we close this as invalid.
Comment #2 by qs.il.paperinik — 2019-01-30T15:41:03Z
In the case of classes, this works. For structs, it does not. If not alias member = field.member; or alias member = Test1.member; in Test2, what kind of alias do you think of? I know none. Both don't work. And for the second example, this is not even slightly possible. The built-in index operator for alias sequences cannot be rebuilt by means of the language, i.e. opIndex with statically known argument. The spec [1] is very vague about alias this, when it works etc. Technically, by the spec, alias this to a built-in type field need not work: It only includes structs, classes, and property member function with no parameters. It does not mention alias sequences at all! One could even argue that it is a bug that alias this to an alias sequence even works. [1]: https://dlang.org/spec/class.html#AliasThis
Comment #3 by robert.schadek — 2024-12-13T19:02:10Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19532 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB