On Fri, 23 Aug 2024, 04:41 Walter Bright via Digitalmars-d, <digitalmars-d@puremagic.com> wrote:
On 8/21/2024 9:33 PM, Manu wrote:
> I don't understand what you mean, or maybe you didn't understand my example?

Quite possibly, because your example hurts my head :-/


> There's only one outer pointer here... it's just typed wrong from the derived
> inner's perspective.

There are two outer pointers. One to Outer2:Outer1, and the other to
Outer1.Inner1.Outer1. Multiple inheritance comes into play when the order of
lookup is not clear and what to do if the identifier being looked up is found
via multiple paths (although in this case is isn't in multiple paths).

A similar thing happened with alias this. When I approved it I did not realize
it was multiple inheritance. The problem eventually showed up, and there are
numerous bug reports about it behaving in baffling ways. Nobody could figure out
a solution to it that made sense, and the result is we cannot remove alias this,
but we cannot fix it either, so it is what it is.

Generally speaking, when there are multiple lookup paths, the inevitable result
is confusion.

I spent a lot of time working out how nested classes and nested functions work.
I'm a bit afraid to start messing with the semantics of it at this point.

A handful of years ago, some contributors thought that having only one "context"
pointer for nested functions was too restrictive, and added the ability for a
second. After it was incorporated, simple cases worked as expected. But people
always try more complex cases, it turned into an unresolvable disaster, and was
eventually removed. (Just like alias this, except we're stuck with alias this,
as too much code depends on it.)

I strongly recommend abandoning this design pattern.

P.S: It's not about types, it's about the order in which things are searched for.

I'm not keen to abandon it; I can't imagine any conceivable use for an outer class reference if not exactly this arrangement I show here. This should work, or just delete the feature.

If you can't derive an inner class, then why an inner class at all? Classes exist to be derived, no other reason to use a class and a million reasons against.

I don't see it the way you describe though, you seem to imagine 2 pointers, where I only see one. There's one outer pointer in the base class, simple as that. The only trouble is that it's typed for the base, when in the derived inner it could be re-typed for it's outer.

A simple solution might be that the compiler emit references to outer as (cast(this.super.typeof)outer). That will always work. If the compiler synthesizes that cast when emitting any outer reference, the whole thing will work neatly; there's not 2 pointers, just a bad type. 

Alternatively, make this.outer appropriately shadow super.outer? But from an implementation perspective, I'd be less inclined, because that intonates that there's 2 outer references (2 paths, as you say), when there's not.

It's easy to prove that there's not ACTUALLY 2 outer references, check the size of Inner1 and Inner2, they are the same size. Inner 2 is not one pointer larger than Inner1.