Bug 19232 – ICE when overriding templated method

Status
RESOLVED
Resolution
DUPLICATE
Severity
minor
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-09-07T12:27:24Z
Last change time
2020-03-21T03:56:42Z
Keywords
diagnostic
Assigned to
No Owner
Creator
Michael Galuza

Comments

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 ***