Bug 20233 – opDispatch hides alias this properties

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2019-09-21T03:34:09Z
Last change time
2024-12-13T19:05:42Z
Assigned to
No Owner
Creator
Lorenzo Cogotti
See also
https://issues.dlang.org/show_bug.cgi?id=6434
Moved to GitHub: dmd#17924 →

Comments

Comment #0 by micia — 2019-09-21T03:34:09Z
In presence of `alias this`, `opDispatch` causes the compiler to ignore any plain member of the aliased field which is not a property nor a callable method. This reduces `alias this` usefulness and is possibly a bug. This is possibly caused by the fact that `opDispatch` takes precedence over `alias this`. ----- module main; struct Point { int[2] coords; alias coords this; auto opDispatch(string name, A...)(args) { return mixin("this.coords." ~ name ~ "(args)"); } } void main() { import std.stdio; Point p; writeln(p.ptr, p.length); } ----- $ dmd alias-dispatch.d alias-dispatch.d(20): Error: no property ptr for type Point alias-dispatch.d(20): Error: no property length for type Point
Comment #1 by micia — 2019-09-21T03:47:20Z
Sorry, there was a typo in my code listing, here is the correct version, producing the same errors: ----- module main; struct Point { int[2] coords; alias coords this; auto opDispatch(string name, A...)(A args) { return mixin("this.coords." ~ name ~ "(args)"); } } void main() { import std.stdio; Point p; writeln(p.ptr, p.length); }
Comment #2 by maxsamukha — 2019-09-21T07:36:50Z
It fails because you are trying apply a function call to a property. The error message is utterly misleading, though: void main() { int[2] x; x.ptr(); } test.d(22): Error: no property ptr for type int[2] // wtf?
Comment #3 by micia — 2019-09-21T08:47:33Z
You are right, looking into the implementation of `std.typecons.Proxy` I have noticed that the process to forward calls/access to an `alias this` from `opDispatch()` is more involved than that. Thus I am changing the importance of this report to `Enhancement`, since I still stand by the opinion that the error message is quite misleading and might be improved. Also, probably the `opDispatch()` inner workings would need to be clarified a little bit better in the language reference: https://dlang.org/spec/operatoroverloading.html#dispatch Since, by just reading, one can only obtain partial and at times confusing information. I had to look into the linked bug report to find out that it has precedence over `alias this`, and found out by trial and error that it also has precedence over UFCS.
Comment #4 by schveiguy — 2019-09-22T14:40:58Z
opDispatch should be considered before alias this, but apparently it disables the alias this completely. I thought this would fix the problem but it doesn't: ------- auto opDispatch(string name, A...)(A args) if(args.length > 0) { return mixin("this.coords." ~ name ~ "(args)"); } ------- It now simply says there's no property ptr or length for Point. So I think even though the original bug report was fixed, it wasn't fully fixed. I think the above should work. As of now, the alias this is completely ignored.
Comment #5 by maxsamukha — 2019-09-22T15:28:46Z
'alias this' is irrelevant. The original test case fails because the array's .ptr property is called as a function. See the example in my previous comment (there was a typo: "apply" -> "to apply").
Comment #6 by schveiguy — 2019-09-22T15:51:59Z
(In reply to Max Samukha from comment #5) > 'alias this' is irrelevant. The original test case fails because the array's > .ptr property is called as a function. See the example in my previous > comment (there was a typo: "apply" -> "to apply"). Yes, original test case fails for a different reason, but alias this isn't usable if you have opDispatch, which is definitely a bug I would think. It should trickle down to alias this if opDispatch doesn't handle it. e.g.: ----- struct S { int length; } struct T { S s; alias s this; int opDispatch(string fn, Args...)(Args args) if(fn != "length") { return 5; } } void main() { T t; import std.stdio; writeln(t.length); } ------- Error: no property length for type T If you comment out opDispatch it works.
Comment #7 by maxsamukha — 2019-09-22T16:18:15Z
(In reply to Steven Schveighoffer from comment #6) > (In reply to Max Samukha from comment #5) > > 'alias this' is irrelevant. The original test case fails because the array's > > .ptr property is called as a function. See the example in my previous > > comment (there was a typo: "apply" -> "to apply"). > > Yes, original test case fails for a different reason, but alias this isn't > usable if you have opDispatch, which is definitely a bug I would think. It > should trickle down to alias this if opDispatch doesn't handle it. > > e.g.: > Ahh, got it. That's definitely a bug.
Comment #8 by john.michael.hall — 2020-06-04T19:23:27Z
Just ran into this. I have two examples below. The first is with structs and alias this and the second is with classes. The class example compiles without error, but the struct one fails to compile. How classes behave is how I would expect structs to, and I was surprised when they didn't. Consider also the diamond problem with multiple inheritance. The way classes work in D is that there is only one way to call a member or member function. Thus, opDispatch acts like overriding any base member function calls. alias this works this way most of the time in that a function in the derived struct will override one in the base struct. However, the doesn't hold with opDispatch. unittest { static struct Foo { int value; int foo() { return value + 1; } } static struct Bar { Foo x; alias x this; int opDispatch(string op)() if (op == "bar") { return x.foo; } } Bar x = Bar(Foo(1)); assert(x.bar == 2); assert(x.foo == 2); assert(x.value == 1); } unittest { static class Foo { int value; this(int x) { value = x; } int foo() { return value + 1; } } static class Bar : Foo { this(int x) { super(x); } int opDispatch(string op)() if (op == "bar") { return foo; } } Bar x = new Bar(1); assert(x.foo == 2); assert(x.bar == 2); assert(x.value == 1); }
Comment #9 by robert.schadek — 2024-12-13T19:05:42Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17924 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB