On Tuesday, 1 September 2015 at 01:40:29 UTC, deadalnix wrote:
Problem arise with templates, for instance:

export void foo(T)(T t) { bar(); }

private void bar() { import std.stdio; writeln("bar was called"); }

Here bar is called. Problem is, foo can be instantiated in a different module than bar is compiled in. As bar is not exported, things will fail to link.

When compiling the module with bar, foo is not instantiated and the compiler has no way to know that this template may use bar (the template is simple here but it could be arbitrarily complex in practice).

Am I right so far ?

Yep, got it exactly right.


Good, then, what is the solution ?

Something like this

Error : template foo is marked as export but not instantiated within any unittest export

To fix, add API test / example:

unittest export {
    foo(42);
}

Compiler sees that unittest export has created `foo!int` and checks what non-template functions get called from that instance (I may be mistaken but all necessary information for that is known once we have actual instance
for an argument set).

Of course, if some branches are missing in unittest export, it will still cause linker errors - that is why fixing linked issue with coverage becomes
pretty important.

Note that this is a reason why I like trait or whatever so that the compiler can figure out what is going on in the template before instantiating it. I tried this road with SDC at first, but the amount of infos that the compiler can infer from D template is way too small for it to be worth it.

Yep, this is why I feel that such a solution will feel dirty if you get used to something like traits which allows for full analysis without instantiating. But within existing semantics it does not seem possible,
it simply allows too much.

Reply via email to