Comment #0 by riddlermichael — 2018-09-07T12:27:24Z
Consider this code:
---
class Unknown;
abstract class Foo(T : Unknown) {
Object get(this D)() {
return (cast(D) this).get();
}
}
class Foo(T) : Foo!Unknown {
T t;
this() {
}
this(T t) {
this.t = t;
}
override T get() {
return t;
}
void set(T t) {
this.t = t;
}
}
void main() {
auto foo = new Foo!Object();
Foo!Unknown afoo = foo;
auto t = afoo.get();
}
---
It crashes:
---
DMD v2.082.0-beta.1
predefs DigitalMars Windows LittleEndian D_Version2 all D_InlineAsm D_InlineAsm_X86 X86 Win32 CRuntime_DigitalMars assert D_ModuleInfo D_Exceptions D_TypeInfo D_HardFloat
binary C:\D\dmd2\windows\bin\dmd.exe
version v2.082.0-beta.1
config C:\D\dmd2\windows\bin\sc.ini
DFLAGS -IC:\D\dmd2\windows\bin\..\..\src\phobos -IC:\D\dmd2\windows\bin\..\..\src\druntime\import
---
object.Error@(0): Access Violation
Without `override` in Foo!T.get it works, but leads to infinite recursion calls of Foo!Unknown.get. Is it just a compiler bug, or it shouldn't work in anyway?
Comment #1 by simen.kjaras — 2018-09-07T13:02:40Z
Further reduced:
abstract class Bar {
void get(A)() { }
}
class Foo : Bar {
override void get() { }
}
unittest {
Bar foo = new Foo();
foo.get();
}
Now, this shouldn't actually work, since template methods are implicitly final (and can't be made virtual in any way). If Bar.get is made into a final, non-templated method, you get the message `Foo.get cannot override final function Bar.get`. The correct error message in this case would be `Foo.get cannot override template function Bar.get`.
(note that the stack trace on the ICE varies wildly with changes in the code above - adding or removing template-ness of Foo and Bar, as well as removing the Unknown class, completely changes it. This could thus be an issue in more than one source code location)
Comment #2 by riddlermichael — 2018-09-07T14:49:31Z
(In reply to Simen Kjaeraas from comment #1)
> Further reduced:
>
> abstract class Bar {
> void get(A)() { }
> }
>
> class Foo : Bar {
> override void get() { }
> }
>
> unittest {
> Bar foo = new Foo();
> foo.get();
> }
>
> Now, this shouldn't actually work, since template methods are implicitly
> final (and can't be made virtual in any way). If Bar.get is made into a
> final, non-templated method, you get the message `Foo.get cannot override
> final function Bar.get`. The correct error message in this case would be
> `Foo.get cannot override template function Bar.get`.
>
> (note that the stack trace on the ICE varies wildly with changes in the code
> above - adding or removing template-ness of Foo and Bar, as well as removing
> the Unknown class, completely changes it. This could thus be an issue in
> more than one source code location)
Thank you for detailed explanation! Anyway, it's ICE)
Comment #3 by razvan.nitu1305 — 2018-09-09T11:19:17Z
(In reply to Simen Kjaeraas from comment #1)
> Further reduced:
>
> abstract class Bar {
> void get(A)() { }
> }
>
> class Foo : Bar {
> override void get() { }
> }
>
> unittest {
> Bar foo = new Foo();
> foo.get();
> }
>
> Now, this shouldn't actually work, since template methods are implicitly
> final (and can't be made virtual in any way). If Bar.get is made into a
> final, non-templated method, you get the message `Foo.get cannot override
> final function Bar.get`. The correct error message in this case would be
> `Foo.get cannot override template function Bar.get`.
>
> (note that the stack trace on the ICE varies wildly with changes in the code
> above - adding or removing template-ness of Foo and Bar, as well as removing
> the Unknown class, completely changes it. This could thus be an issue in
> more than one source code location)
PR: https://github.com/dlang/dmd/pull/8665 fixes this. With that patch the error message is:
issue.d(8): Error: function void issue.Foo.get() does not override any function, did you mean to override template issue.Bar.get(A)()?
issue.d(8): Functions are the only declarations that may be overriden
I suggest closing this as fixed.
Comment #4 by razvan.nitu1305 — 2018-09-09T11:31:11Z
However, the following code compiles successfully :
abstract class Bar {
void get(A)() { }
}
class Foo : Bar {
override void get(A)() { }
}
unittest {
Bar foo = new Foo();
foo.get!(int)();
}
compiles successfully and the method in the Bar is called.
Comment #5 by b2.temp — 2019-03-02T14:08:18Z
*** This issue has been marked as a duplicate of issue 11455 ***