Bug 23277 – alias to mixin template breaks selective overriding of mixin template member

Status
NEW
Severity
minor
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-07-31T00:16:57Z
Last change time
2024-12-13T19:24:03Z
Assigned to
No Owner
Creator
Adam D. Ruppe
Moved to GitHub: dmd#20136 →

Comments

Comment #0 by destructionator — 2022-07-31T00:16:57Z
Easier to describe in code: ``` interface A { void foo(); void foo(int); } mixin template C(alias impl, Iface) { void foo(){ return impl.foo(); } void foo(int p){ return impl.foo(p); } } class B : A { A impl; mixin C!(impl, A) c; void foo(int) {} alias foo = c.foo; } ``` Error: function `test.B.C!(impl, A).foo(int p)` conflicts with previous declaration at test.d(14) This pattern normally works to selectively override a function from the mixin template, but the circular definition seems to trigger an order of semantic bug or something.
Comment #1 by destructionator — 2022-07-31T00:19:46Z
Actually, I don't think I completely reduced this; you can remove the alias param and still get it by just mentioning `impl` in the body. This is further reduced: ``` interface A { void foo(); void foo(int); } mixin template C() { void foo(){ return impl.foo(); } void foo(int p){ return impl.foo(p); } } class B : A { A impl; mixin C!() c; void foo(int) {} alias foo = c.foo; } ``` The alias line in the class is necessary to trigger the thing.
Comment #2 by razvan.nitu1305 — 2022-08-09T12:55:24Z
(In reply to Adam D. Ruppe from comment #1) > Actually, I don't think I completely reduced this; you can remove the alias > param and still get it by just mentioning `impl` in the body. > > This is further reduced: > > ``` > interface A { > void foo(); > void foo(int); > } > > mixin template C() { > void foo(){ return impl.foo(); } > void foo(int p){ return impl.foo(p); } > } > > class B : A { > A impl; > mixin C!() c; > void foo(int) {} > alias foo = c.foo; > } > ``` > > The alias line in the class is necessary to trigger the thing. Hmm, to me it seems that you are trying to insert `void foo(int p)` in the same overload set as `void foo(int)`. Shouldn't this be illegal? Otherwise, once you call B.foo how can the compiler know which function should be called?
Comment #3 by destructionator — 2022-08-09T13:04:17Z
The overload set merging actually works perfectly fine. Declarations in the class itself override things that are mixed in, so it will always call the one from the class if the arguments match. The problem here is the compiler doesn't allow it with the specific scenario when you are trying to forward the call to a member variable.
Comment #4 by robert.schadek — 2024-12-13T19:24:03Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20136 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB