I'm using DMD2.053 on Windows7 x64 My test case: - I have a all in one console application which output "true true" - I have a project with the exact same code split into a static lib and an exe and it output "false false" The bug is that the output is different! === first the all in one, outputing "true, true" ========= module main; import std.variant; import std.stdio; import std.metastrings : Format; import std.traits; public mixin template property(T, string name) { mixin(Format!("private T _%s; @property public T %s() { return _%s; } @property public void %s(T value) { _%s = value; }", name, name, name, name, name)); } interface IInter { } class Foo : IInter { static this() { Compiled!(Foo, "FP"); Compiled!(Foo, "Subfoo"); } @property public Foo FP() { return new Foo(); } @property public void FP(Foo f) { } mixin property!(Foo, "Subfoo"); } int main(string[] argv) { return 0; } void Compiled(T, string memberName)() { T t; writeln(mixin( "__traits(compiles, t." ~memberName ~" = (" ~typeof(__traits(getMember, T, memberName)).stringof ~").init)" )); } ============================================== now the splitted program, outputting "false, false" whereas it should output "true, true" just like above, shouldn't it!?! ===== lib.d ==== module lib; import std.variant; import std.stdio; import std.metastrings : Format; import std.traits; public mixin template property(T, string name) { mixin(Format!("private T _%s; @property public T %s() { return _%s; } @property public void %s(T value) { _%s = value; }", name, name, name, name, name)); } interface IInter { } void Compiled(T, string memberName)() { T t; writeln(mixin( "__traits(compiles, t." ~memberName ~" = " ~typeof(__traits(getMember, T, memberName)).stringof ~").init" )); } ====== main.d ===== module main; import lib; class Foo : IInter { static this() { Compiled!(Foo, "FP"); Compiled!(Foo, "Subfoo"); } @property public Foo FP() { return new Foo(); } @property public void FP(Foo f) { } mixin property!(Foo, "Subfoo"); } int main(string[] argv) { return 0; } ===================== buildrun.bat ========= dmd -lib -g -debug -X -of"lib1.lib" lib.d dmd -g -debug -X main.d lib1.lib main ====================================
This is not a bug. See section "Instantiation Scope" of http://www.d-programming-language.org/template.html . > TemplateInstantances are always performed in the scope of where the > TemplateDeclaration is declared, with the addition of the template parameters > being declared as aliases for their deduced types.
How does the template scope has anything to do with this bug? In plain English I'm testing that the property can be set. I.e. class Foo { @property public Foo Subfoo() {} @property public Foo Subfoo2() {} @property public void Subfoo2(Foo f) {} } in the above class Subfoo can't be set, Subfoo2 can. I'm testing it with Foo f, __traits(compile, f.Suboo = Foo.init) __traits(compile, f.Suboo2 = Foo.init) This seems to work erratically!
Not understanding the explanation I can't claim it wrong... Nonetheless the work around I found seems to indicate to me that the explanation was, at the very least (for what I understand) completely irrelevant. I replaced: writeln(mixin( "__traits(compiles, t." ~memberName ~" = ("~typeof(__traits(getMember, T, memberName)).stringof ~").init)" )); With: writeln(mixin( "__traits(compiles, t." ~memberName ~" = (typeof(t."~memberName ~")).init)" )); And it worked. Still using library and exe.
Sorry, it looked like you were instantiating a template in a scope where a symbol passed by name as a string didn't exist. You may want to reduce your example to the smallest amount of code which illustrates the bug for clarity.
I found a way to reduce the sample even further. 1st no need to have 2 project (lib & exe). All in the same exe (but different module) is enough to cause the bug. ==== main.d ==== module main; import lib; class Foo { static this() { Compiled!(Foo, "Subfoo"); } @property public Foo Subfoo() { return null; } @property public void Subfoo(Foo f) { } } int main(string[] argv) { return 0; } ====== lib.d ====== module lib; import std.traits; import std.stdio; void Compiled(T, string memberName)() { T t; writeln(mixin( "__traits(compiles, t." ~memberName ~" = (" ~typeof(__traits(getMember, T, memberName)).stringof ~").init)" )); } =============== this output "false", whereas it should output "true" a work around (and simpler code in fact) is to use the following simpler mixin (in Compiled) --- writeln(mixin( "__traits(compiles, t." ~memberName ~" = (typeof(t." ~memberName ~")).init)" )); --- Yet I do think this sample highlight a compiler bug
This is not bug. In lib.d, you can't access Foo by name (without importing main). ---- lib.d ---- void Compiled(T, string memberName)() { T t; // ok Foo foo; // error! } ----