Bug 23377 – class method overloading with same name doesn't work for base classes

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-09-26T17:52:05Z
Last change time
2022-10-03T13:14:50Z
Assigned to
No Owner
Creator
Luís Ferreira

Comments

Comment #0 by contact — 2022-09-26T17:52:05Z
The compiler doesn't check the base class overloads when the correct overload is provided, only on the base class, but contains an incorrect overload on the derived class. If the derived class doesn't have any overload, it works. E.g.: ================= struct Foo { void foo(Bar b) { b.bar(this); } } struct Foobar {} struct Foobar2 {} class Base { void bar(Foo f) {} void bar(Foobar2 f) {} } class Bar : Base { void call() { Foo f; f.foo(this); } // if you comment this it will choose the right overload, therefore it works void bar(Foobar f) {} }
Comment #1 by snarwin+bugzilla — 2022-09-26T19:43:13Z
Simplified example: --- void main() { Derived d; A a; d.fun(a); } struct A {} struct B {} struct C {} class Base { void fun(A a) {} void fun(C c) {} } class Derived : Base { // if you comment this it will call Base.fun(A) void fun(B b) {} } --- I think what's happening here is that Base.fun and Derived.fun are in separate overload sets, and the derived-class overload set shadows the base-class one. Examining the overload sets with reflection appears to support this hypothesis: --- struct A {} struct B {} struct C {} class Base { void fun(A a) {} void fun(C c) {} } class Derived1 : Base { // if you comment this it will call Base.fun(A) void fun(B b) {} } // prints: tuple(fun) pragma(msg, __traits(getOverloads, Derived1, "fun")); class Derived2 : Base {} // prints tuple(fun, fun) pragma(msg, __traits(getOverloads, Derived2, "fun")); ---
Comment #2 by razvan.nitu1305 — 2022-09-27T05:47:16Z
This is intended behavior. For more information check [1]. Long story short, the current mechanism is in place to prevent hijacking. I guess an argument can be made that in this case neither A nor C are implicitly convertible to B, but to me this just seems like adding special cases when the alternative would be to simply use an alias to introduce fun(B) in the same overload set as the other fun methods. I am inclined to close this as a WONTFIX. Either way, this is not a bug, but an enhancement request by the current language rules. [1] https://dlang.org/articles/hijack.html#derived-class-members
Comment #3 by contact — 2022-09-29T11:59:04Z
I didn't know that this was intentional, tbh. It makes some sense, given the rationale and given that there's a clean alternative to behave correctly, although, I think this should be more explicit on the language documentation/spec, then, at least, the way to do it, with an example using an alias.
Comment #4 by nick — 2022-10-02T15:28:03Z
(In reply to Luís Ferreira from comment #3) > although, I think this should be more > explicit on the language documentation/spec, then, at least, the way to do > it, with an example using an alias. It is in the spec: https://dlang.org/spec/function.html#function-inheritance However, it would be easier to find if the whole virtual functions section was moved to the class page.
Comment #5 by nick — 2022-10-03T13:14:50Z
I have filed issue 23384 so the compiler mentions the base method is hidden.