digitalmars.D.learn - Mixin template parameter overloading bug?
- Andrey Zherikov (40/40) Jun 13 The simplest code that shows the issue:
- monkyyy (22/62) Jun 13 I believe every change in compilation from (top level)
- Andrey Zherikov (8/29) Jun 13 Mixin templates and regular templates have different use cases:
- Andrey Zherikov (16/16) Jun 13 On Saturday, 14 June 2025 at 00:02:32 UTC, Andrey Zherikov wrote:
- monkyyy (21/38) Jun 13 https://dlang.org/spec/template-mixin.html
- Andrey Zherikov (31/74) Jun 13 Modified your example a bit.
- monkyyy (13/91) Jun 13 ```d
- Andrey Zherikov (2/17) Jun 14 I created https://github.com/dlang/dmd/issues/21447
The simplest code that shows the issue: ```d struct S{} template f(void function(S) F) {} template f(int function(S) F) {} mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function // mixin f!((_) => 0); // ^ // while looking for match for `f!((_) => 0)` // mixin f!((_) => 0); ``` If I swap `template f` declarations: ```d struct S{} template f(int function(S) F) {} template f(void function(S) F) {} mixin f!((_) {}); // Error: function `onlineapp.__lambda_L8_C10(__T1)(_)` has no `return` statement, but is expected to return a value of type `int` // mixin f!((_) {}); // ^ // while looking for match for `f!((_) // { // } // )` // mixin f!((_) {}); // ^ mixin f!((_) => 0); ``` But if I remove `S` from template parameters, everything works: ```d template f(int function() F) {} template f(void function() F) {} mixin f!(() {}); mixin f!(() => 0); ``` Is this a bug somewhere in compiler or in my code?
Jun 13
On Saturday, 14 June 2025 at 00:02:32 UTC, Andrey Zherikov wrote:The simplest code that shows the issue: ```d struct S{} template f(void function(S) F) {} template f(int function(S) F) {} mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function // mixin f!((_) => 0); // ^ // while looking for match for `f!((_) => 0)` // mixin f!((_) => 0); ``` If I swap `template f` declarations: ```d struct S{} template f(int function(S) F) {} template f(void function(S) F) {} mixin f!((_) {}); // Error: function `onlineapp.__lambda_L8_C10(__T1)(_)` has no `return` statement, but is expected to return a value of type `int` // mixin f!((_) {}); // ^ // while looking for match for `f!((_) // { // } // )` // mixin f!((_) {}); // ^ mixin f!((_) => 0); ``` But if I remove `S` from template parameters, everything works: ```d template f(int function() F) {} template f(void function() F) {} mixin f!(() {}); mixin f!(() => 0); ``` Is this a bug somewhere in compiler or in my code?I believe every change in compilation from (top level) declaration order is considered a compiler bug However, I see.... Allot of issues with this code, Id want to see something near functional code around this subject; its worth poking, but its possible every possible way to make this code work would eliminate the pattern here for example this compiles: ```d import std; struct S{} template f(void function(S) F) {alias f=void;} template f(int function(S) F) {alias f=int;} unittest{ alias a=f!((_) {}); alias b=f!((_) => 0); a.stringof.writeln; b.stringof.writeln; } ``` mixin templates vs declaration templates was a bad decision in my opinion but thats old news.
Jun 13
On Saturday, 14 June 2025 at 00:26:27 UTC, monkyyy wrote:I believe every change in compilation from (top level) declaration order is considered a compiler bug However, I see.... Allot of issues with this code, Id want to see something near functional code around this subject; its worth poking, but its possible every possible way to make this code work would eliminate the pattern here for example this compiles: ```d import std; struct S{} template f(void function(S) F) {alias f=void;} template f(int function(S) F) {alias f=int;} unittest{ alias a=f!((_) {}); alias b=f!((_) => 0); a.stringof.writeln; b.stringof.writeln; } ``` mixin templates vs declaration templates was a bad decision in my opinion but thats old news.Mixin templates and regular templates have different use cases: the former can inject declaration on caller's site while the latter can't. In my case mixin template generates top-level `main()` function but the content of the template is not important here. Also using `alias F` as template parameter doesn't allow me to introspect the actual type.
Jun 13
On Saturday, 14 June 2025 at 00:02:32 UTC, Andrey Zherikov wrote: Simplified test case a bit more. This works: ```d template f(void function(int) F) {} template f(int function(int) F) {} mixin f!((int _) {}); mixin f!((int _) => 0); mixin f!((int) {}); mixin f!((int) => 0); mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function ``` Can anyone explain why adding type of the parameter in lambda (`int`) makes this working?
Jun 13
On Saturday, 14 June 2025 at 01:46:31 UTC, Andrey Zherikov wrote:On Saturday, 14 June 2025 at 00:02:32 UTC, Andrey Zherikov wrote: Simplified test case a bit more. This works: ```d template f(void function(int) F) {} template f(int function(int) F) {} mixin f!((int _) {}); mixin f!((int _) => 0); mixin f!((int) {}); mixin f!((int) => 0); mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function ``` Can anyone explain why adding type of the parameter in lambda (`int`) makes this working?https://dlang.org/spec/template-mixin.html Your still mixing syntax; mixin templates are suppose to be a separate system according to the spec. ```d import std; void f(int function(int) F)(){"int".writeln;} void f(void function(int) F)(){"void".writeln;} unittest{ f!((_) {}); f!((_) => 0); } mixin template g(int function(int) F){string s1="int";} mixin template g(void function(int) F){string s2="void";} unittest{ mixin g!((_) {}); mixin g!((_) => 0); s1.writeln; s2.writeln; } ```
Jun 13
On Saturday, 14 June 2025 at 02:10:03 UTC, monkyyy wrote:On Saturday, 14 June 2025 at 01:46:31 UTC, Andrey Zherikov wrote:Modified your example a bit. This works: ```d mixin template f(void function(int) F) { void s1() {"void".writeln; } } mixin template f(int function(int) F) { void s2() {"int".writeln; } } void main() { mixin f!((_) {}); mixin f!((_) => 0); s1(); s2(); } ``` This does not: ```d mixin template f(void function(int) F) { void s1() {"void".writeln; } } mixin template f(int function(int) F) { void s2() {"int".writeln; } } mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function void main() { s1(); s2(); } ```On Saturday, 14 June 2025 at 00:02:32 UTC, Andrey Zherikov wrote: Simplified test case a bit more. This works: ```d template f(void function(int) F) {} template f(int function(int) F) {} mixin f!((int _) {}); mixin f!((int _) => 0); mixin f!((int) {}); mixin f!((int) => 0); mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function ``` Can anyone explain why adding type of the parameter in lambda (`int`) makes this working?https://dlang.org/spec/template-mixin.html Your still mixing syntax; mixin templates are suppose to be a separate system according to the spec. ```d import std; void f(int function(int) F)(){"int".writeln;} void f(void function(int) F)(){"void".writeln;} unittest{ f!((_) {}); f!((_) => 0); } mixin template g(int function(int) F){string s1="int";} mixin template g(void function(int) F){string s2="void";} unittest{ mixin g!((_) {}); mixin g!((_) => 0); s1.writeln; s2.writeln; } ```
Jun 13
On Saturday, 14 June 2025 at 02:16:58 UTC, Andrey Zherikov wrote:On Saturday, 14 June 2025 at 02:10:03 UTC, monkyyy wrote:```d import std; mixin template f(int function(int) F){} mixin template f(void function(int) F){unittest{"void".writeln;}} //mixin f!((_){}); //FAILS mixin template g(void function(int) F){unittest{"void".writeln;}} mixin template g(int function(int) F){} mixin g!((_){}); //works ``` this example makes it purely a compiler bug I cant escape any useful information(I tried `typeof(return)`), seems to be limited to just void return functionsOn Saturday, 14 June 2025 at 01:46:31 UTC, Andrey Zherikov wrote:Modified your example a bit. This works: ```d mixin template f(void function(int) F) { void s1() {"void".writeln; } } mixin template f(int function(int) F) { void s2() {"int".writeln; } } void main() { mixin f!((_) {}); mixin f!((_) => 0); s1(); s2(); } ``` This does not: ```d mixin template f(void function(int) F) { void s1() {"void".writeln; } } mixin template f(int function(int) F) { void s2() {"int".writeln; } } mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function void main() { s1(); s2(); } ```On Saturday, 14 June 2025 at 00:02:32 UTC, Andrey Zherikov wrote: Simplified test case a bit more. This works: ```d template f(void function(int) F) {} template f(int function(int) F) {} mixin f!((int _) {}); mixin f!((int _) => 0); mixin f!((int) {}); mixin f!((int) => 0); mixin f!((_) {}); mixin f!((_) => 0); // Error: cannot return non-void from `void` function ``` Can anyone explain why adding type of the parameter in lambda (`int`) makes this working?https://dlang.org/spec/template-mixin.html Your still mixing syntax; mixin templates are suppose to be a separate system according to the spec. ```d import std; void f(int function(int) F)(){"int".writeln;} void f(void function(int) F)(){"void".writeln;} unittest{ f!((_) {}); f!((_) => 0); } mixin template g(int function(int) F){string s1="int";} mixin template g(void function(int) F){string s2="void";} unittest{ mixin g!((_) {}); mixin g!((_) => 0); s1.writeln; s2.writeln; } ```
Jun 13
On Saturday, 14 June 2025 at 03:17:09 UTC, monkyyy wrote:```d import std; mixin template f(int function(int) F){} mixin template f(void function(int) F){unittest{"void".writeln;}} //mixin f!((_){}); //FAILS mixin template g(void function(int) F){unittest{"void".writeln;}} mixin template g(int function(int) F){} mixin g!((_){}); //works ``` this example makes it purely a compiler bug I cant escape any useful information(I tried `typeof(return)`), seems to be limited to just void return functionsI created https://github.com/dlang/dmd/issues/21447
Jun 14