A problem found by Jesse Phillips. This is Java program: class Base {} class Derived extends Base {} abstract class Abstract { abstract Base foo(); } class Concrete extends Abstract { @Override Derived foo() { return new Base(); } } class Test {} The javac compiler prints: Test.java:11: incompatible types return new Base(); ^ required: Derived found: Base 1 error But dmd 2.047 compiles this D2 program with no errors: class Base {} class Derived : Base {} abstract class Abstract { abstract Base foo(); } class Concrete : Abstract { override Derived foo() { return new Base; } } void main() {}
Slightly extended example shows that the returned instance is of type derived!, but constructor is not called. class Base {} class Derived : Base { this () { x = 1; } int x; } abstract class Abstract { abstract Base foo(); } class Concrete : Abstract { override Derived foo() { return new Base; } } void main() { auto c = new Concrete; auto x = c.foo(); writeln (typeof(x).stringof); // prints Derived (even it is result of 'new Base') writeln (x.x); // prints 0 (wich means Derived's constructor is not called) x.x = 2; writeln (x.x); // prints 2 }
> auto c = new Concrete; > auto x = c.foo(); > writeln (typeof(x).stringof); // prints Derived (even it is result of 'new > Base') You're doing it wrong. typeof(x) is evaluated at compile time and always gives the declared type even if x==null The correct code is --- auto c = new Concrete; auto x = c.foo(); writeln(x.classinfo.name); // Base ---
> x.x = 2; > writeln (x.x); // prints 2 This just writes to the memory after the allocated Base object, probably corrupting heap.
https://github.com/D-Programming-Language/dmd/pull/137
https://github.com/D-Programming-Language/dmd/commit/b3bbae5302ed7b68d98134d389dfc8d3cc735119 https://github.com/D-Programming-Language/dmd/commit/1209914a3cca53bd2026bedccbae6118026b666c