Bug in template mixin
From https://forum.dlang.org/post/[email protected]:
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
Expected behavior: both cases work
expected behavior is that both case should fail as this is what we can observe once we extract the lambda to an AliasDecl
mixin template g(void function(int) F) {}
mixin template g(int function(int) F){}
alias garg = (_){};
static assert(__traits(isTemplate, garg));
mixin g!garg;
mixin template f(int function(int) F) {}
mixin template f(void function(int) F) {}
alias farg = (_){};
static assert(__traits(isTemplate, farg));
mixin f!farg;
where both TemplateMixin fail with the same errors.
So it seems that there's some code in the compiler that allows to instantiate the arg but that is not made consistently.
expected behavior is that both case should fail as this is what we can observe once we extract the lambda to an AliasDecl
mixin template g(void function(int) F) {} mixin template g(int function(int) F){}
alias garg = (_){}; static assert(__traits(isTemplate, garg)); mixin g!garg;
mixin template f(int function(int) F) {} mixin template f(void function(int) F) {}
alias farg = (_){}; static assert(__traits(isTemplate, farg)); mixin f!farg; where both TemplateMixin fail with the same errors.
So it seems that there's some code in the compiler that allows to instantiate the arg but that is not made consistently.
This is different thing because if I remove override, your code still doesn't compile:
mixin template g(void function(int) F) {}
//mixin template g(int function(int) F){}
alias garg = (_){};
static assert(__traits(isTemplate, garg));
mixin g!garg;
// Error: mixin `onlineapp.g!(__lambda_L6_C1)` does not match template declaration `g(void function(int) F)`
// mixin g!garg;
// ^
The original case fails when mixin is at top level. If mixin is placed inside a function - everything works:
mixin template f(int function(int) F){}
mixin template f(void function(int) F){}
mixin template g(void function(int) F){}
mixin template g(int function(int) F){}
//mixin f!((_){}); //fails here
mixin g!((_){}); //works
void main()
{
mixin f!((_){}); //works if placed inside a function
mixin g!((_){}); //works
}
Note how that never works if you start using aliases, whether local or global:
mixin template f(int function(int) F){}
mixin template f(void function(int) F){}
mixin template g(void function(int) F){}
mixin template g(int function(int) F){}
alias global_garg = (_){};
mixin g!global_garg; //error
void main()
{
alias local_farg = (_){};
mixin f!local_farg; //error
alias local_garg = (_){};
mixin g!local_garg; //error
}