Bug 5380 – alias this is not considered with superclass lookup

Status
REOPENED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-12-27T03:59:11Z
Last change time
2024-12-13T17:54:38Z
Assigned to
No Owner
Creator
Max Samukha
See also
https://issues.dlang.org/show_bug.cgi?id=13189, https://issues.dlang.org/show_bug.cgi?id=8663
Moved to GitHub: dmd#17522 →

Comments

Comment #0 by samukha — 2010-12-27T03:59:11Z
class A { } class B { A a; alias a this; } class C : B { } void main() { A a = new C; // error } Error: cannot implicitly convert expression (new C) of type test.C to test.A Since C is a subtype of B (via inheritance) and B is a subtype of A (via "alias this"), C should be implicitly convertible to A.
Comment #1 by bugzilla — 2010-12-27T13:33:28Z
Yes, I see the problem. Never thought of that.
Comment #2 by samukha — 2012-11-28T07:16:16Z
This one is blocking a design for QtD (and potentially other C++ projects using single inheritance with interfaces) that should allow at the cost of relatively small constant overhead to avoid: 1) unnecessary and undesirable allocations or lookups of wrapper objects for object pointers returned by the C++ code. 2) bloating the library with virtual call dispatchers for objects that are never inherited in D code. Very roughly: // Instead of classes, fat pointers are generated for C++ classes: struct QObject { bool isDWrapper; void* pointerToCppObject; // a virtual void foo() { if (isDWrapper) // dispatch to the D override else // make static call to C++ } enum dispatchers = q{ void foo() { // dispatch to C++ } }; } // Library class Inherit(T) { T ref_; alias ref_ this; mixin(T.dispatchers); this() { isDWrapper = true; } } // User class MyObject : Inherit!QObject { override void foo() { ... super.foo(); ... } } // Some function taking a QObject void bar(QObject obj) { obj.foo(); } void main() { // Here is the problem: MyObject is not a subtype of QObject bar(new MyObject); } The Inherit template subtypes the struct and provides the implementation of the overrides dispatching calls to the C++ side. If the user does not inherit from a Qt class (which will be true for most classes), the overrides are never compiled into the library. When receiving an object from the C++ side, we do not need to allocated a wrapper objects, just initialize the fat pointer with the relevant information. I am not sure whether the craziness of the above is going to make it into the project but a prototype I've created does work. Now that we can link to 64-bit C++ libraries directly on windows, we *maybe* could try to use (and improve) extern(C++) interfaces in order to avoid the complications. I am still not sure what to do with 32-bit Windows and would rather give a try to the design described.
Comment #3 by verylonglogin.reg — 2013-11-09T04:38:39Z
*** Issue 5973 has been marked as a duplicate of this issue. ***
Comment #4 by verylonglogin.reg — 2013-11-09T04:41:24Z
From Kenji Hara's Issue 5973 description: Following should compile, but not. (In comment, -> is superclass lookup, => is alias this lookup) --- class A { int a = 1; } class B { int b = 2; } class C: A { B obj; alias obj this; this() { obj = new B(); } } class X: C { } void main() { auto c = new C(); assert(c.a == 1); // lookup C -> A, OK assert(c.b == 2); // lookup C => B, OK auto x = new X(); assert(x.a == 1); // lookup X -> C -> A, OK assert(x.b == 2); // lookup X -> C => B, NG (Line 17) } --- test.d(17): Error: no property 'b' for type 'test.X' --- ---
Comment #5 by simen.kjaras — 2018-06-28T06:34:13Z
*** Issue 19032 has been marked as a duplicate of this issue. ***
Comment #6 by razvan.nitu1305 — 2018-10-09T17:29:22Z
Comment #7 by bugzilla — 2018-11-19T10:43:23Z
This is much more of a perplexing problem than it first appears. What order are things looked up in? Is the alias-this looked up first, or the base classes? Or are they looked up as the base classes are looked up? What happens if two different symbols are found via different orderings of when lookups are done? What happens if the same symbol is found via different lookup paths? This is the old multiple inheritance problem from C++, one I had wished to avoid in D. Max Samukha's comment is a way to inherit class types from struct types, one use I had not anticipated, and makes me want to step back and question is this really where we want to go with this? At least with the current implementation, things are a bit straightforward. The base classes are looked at. If not found there, the alias-this is looked at, and that's it.
Comment #8 by alexanderheistermann — 2018-12-02T18:41:23Z
Do we really want multiple inheritance via alias this? I can't imagine how the current situation will be when multi alias this is implemented. @Walter Bright Please think long and hard about this, as if we allow multiple inheritance via alias this, we be encountering the infamous "diamond problem". https://web.archive.org/web/20051024230813/http://www.objectmentor.com/resources/articles/javacpp.pdf
Comment #9 by maxsamukha — 2021-12-24T21:39:03Z
Multiple inheritance fell from grace.
Comment #10 by aldacron — 2021-12-25T02:33:09Z
This shouldn't be closed. Either the implementation needs to be modified to allow it or the spec needs to specify that alias this in a super class is not considered in its subclasses.
Comment #11 by razvan.nitu1305 — 2022-09-08T09:11:15Z
*** Issue 8663 has been marked as a duplicate of this issue. ***
Comment #12 by robert.schadek — 2024-12-13T17:54:38Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17522 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB