On Wednesday, 19 March 2025 at 03:40:28 UTC, Paul Backus wrote:
> What SHOULD this program do?
What do you think it ACTUALLY does?
It should print “outer”, and it actually does.
Obviously, at first I expected it to print: “inner”. But when I saw the result and checked the spec, I think that it works correctly.
There are three non-obvious things ging in here.
Number one: fun(T).fun(string)
is not a regular function, it’s a template. So it doesn’t collide with globally-defined fun(string)
. This is why this program compiles.
Number two: inside eponymous template fun
, fun
refers to the template itself, not to its members. This gives a different result:
template fun(T) {
alias fun = f;
string f(int) => f("hi");
string f(string) => "inner";
}
string f(string) => "outer";
void main() {
import std.stdio;
writeln(fun!int(123)); // sorry, IFTI no longer works
}
Number three: using a type instead of template parameter (of the same type) is enough to break implicit instantiation:
template fun(T) {
string fun(string) => "inner";
}
void main() {
import std.stdio;
writeln(fun("hi")); // error
writeln(fun!string("hi")); // works
}
There are many other ways to break IFTI:
template fun(T) {
alias fun = fun;
string f(T) => "inner";
}
template fun(T) {
template fun(T) {
string fun(T) => "inner";
}
}
I guess it can’t be helped. Usually, though, IFTI failure results in error. In this program, it leads to unforeseen behavior. But such is life on templates.