D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 14363 - [SDC] Error with inheriting nested classes in nested functions
Summary: [SDC] Error with inheriting nested classes in nested functions
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P3 normal
Assignee: No Owner
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2015-03-28 16:57 UTC by Shammah Chancellor
Modified: 2024-12-13 18:41 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Shammah Chancellor 2015-03-28 16:57:30 UTC
```
> rdmd test0165.d
test0165.d(22): Error: class test0165.voldemort.basilisk.GinnyWeasley is nested within basilisk, but super class MarvoloRiddle is nested within voldemort
```


```test0165.d
//T compiles:yes
//T has-passed:yes
//T retval:41
// voldemort class with inheritance and 2 different contexts.

auto voldemort() {
	uint a = 7;
	
	class MarvoloRiddle {
		uint b;
		
		this(uint b) {
			this.b = b + a++;
		}
		
		auto foo() {
			return a + b;
		}
	}
	
	auto basilisk(uint c) {
		class GinnyWeasley : MarvoloRiddle {
			this(uint b) {
				a += c++;
				this.b = b + a++;
			}
			
			auto bar() {
				return foo() + a + c;
			}
		}
		
		return new GinnyWeasley(5);
	}
	
	return basilisk(3);
}

auto buzz(V)(V v) {
	return v.bar();
}

int main() {
	auto v = voldemort();
	return buzz(v);
}

```
Comment 1 Kenji Hara 2015-03-29 04:21:10 UTC
I'm not sure why SDC accepts the code.

The following reduced case is correctly rejected by dmd, because ba.foo() won't work expectedly. Maybe SDC generates wrong code?

void main()
{
    uint x = 7;

    class A
    {
        auto foo()
        {
            return x;
        }
    }

    auto makeB(uint y)
    {
        class B : A
        {
            auto bar()
            {
                return foo() + y;
            }
        }

        return new B(5);
    }

    A a = new A();
    assert(a.foo() == 7);

    auto b = makeB(3);
    assert(b.bar() == 10);

    A ba = b;
    assert(ba.foo() == 7);
}
Comment 2 Shammah Chancellor 2015-03-29 04:55:25 UTC
Your code has a bug?

return new B(5);

Should be:

return new B();


With that, your example compiles and works just fine on SDC.


(In reply to Kenji Hara from comment #1)
> I'm not sure why SDC accepts the code.
> 
> The following reduced case is correctly rejected by dmd, because ba.foo()
> won't work expectedly. Maybe SDC generates wrong code?
> 
> void main()
> {
>     uint x = 7;
> 
>     class A
>     {
>         auto foo()
>         {
>             return x;
>         }
>     }
> 
>     auto makeB(uint y)
>     {
>         class B : A
>         {
>             auto bar()
>             {
>                 return foo() + y;
>             }
>         }
> 
>         return new B(5);
>     }
> 
>     A a = new A();
>     assert(a.foo() == 7);
> 
>     auto b = makeB(3);
>     assert(b.bar() == 10);
> 
>     A ba = b;
>     assert(ba.foo() == 7);
> }
Comment 3 Kenji Hara 2015-03-29 05:04:43 UTC
(In reply to Shammah Chancellor from comment #2)
> Your code has a bug?
> 
> return new B(5);
> 
> Should be:
> 
> return new B();

Yes. Sorry.

> With that, your example compiles and works just fine on SDC.

Hmm, interesting. SDC might use a thunk to get valid context pointer for base classes from the instantiated context.
But it would need some runtime cost and additional vtbl entry. I don't have any knowledge about the SDC backend, but the ABI around nested classes would be different from dmd's.
Comment 4 Kenji Hara 2015-03-29 11:09:22 UTC
Maybe SDC inserts a hidden field to access enclosing scope in each derived classes?

void main() {
    uint x = 7;

    class A {
        int fieldA;
        auto foo() { return x; }
    }

    auto makeB(uint y) {
        class B : A {
            int fieldB;
            auto bar() { return foo() + y; }
        }

        return new B(5);
    }

    A a = new A();
    assert(a.foo() == 7);

    auto b = makeB(3);
    alias B = typeof(b);
    assert(b.bar() == 10);

    pragma(msg, A.fieldA.offsetof);
    pragma(msg, __traits(classInstanceSize, A));
    pragma(msg, B.fieldB.offsetof);
    pragma(msg, __traits(classInstanceSize, B));
}

If B.fieldB.offsetof + int.sizeof + (void*).sizeof <= __traits(classInstanceSize, B), both B and A have their own hidden fields.

Note that it's intentionally disallowed by dmd. With dmd, implicitly insertion of hidden field is limited at most once. At best, it's an incompatibility between dmd and SDC.
Comment 5 Shammah Chancellor 2015-03-29 17:06:59 UTC
I'm not sure about that part of SDC.  I will investigate and see if deadalnix has some input here.
Comment 6 deadalnix 2015-03-29 18:27:37 UTC
(In reply to Shammah Chancellor from comment #5)
> I'm not sure about that part of SDC.  I will investigate and see if
> deadalnix has some input here.

SDC does it by sticking one context in the base and one context in the child.
Comment 7 Kenji Hara 2015-04-12 12:52:51 UTC
(In reply to deadalnix from comment #6)
> (In reply to Shammah Chancellor from comment #5)
> > I'm not sure about that part of SDC.  I will investigate and see if
> > deadalnix has some input here.
> 
> SDC does it by sticking one context in the base and one context in the child.

It's definitely different. dmd inserts at most only one context over the all derived classes. The second context pointer in the child class need to be error in SDC.
Comment 8 deadalnix 2015-04-12 21:03:15 UTC
(In reply to Kenji Hara from comment #7)
> (In reply to deadalnix from comment #6)
> > (In reply to Shammah Chancellor from comment #5)
> > > I'm not sure about that part of SDC.  I will investigate and see if
> > > deadalnix has some input here.
> > 
> > SDC does it by sticking one context in the base and one context in the child.
> 
> It's definitely different. dmd inserts at most only one context over the all
> derived classes. The second context pointer in the child class need to be
> error in SDC.

I see no reason for this limitation.
Comment 9 dlangBugzillaToGithub 2024-12-13 18:41:37 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/18964

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB