On Monday, 4 January 2021 at 15:31:02 UTC, ag0aep6g wrote:
On 04.01.21 16:03, jmh530 wrote:
IMO, this is a better example, even if it's a little more
verbose.
struct Foo(T) {}
alias Bar(T) = Foo!T;
void f(T)(Bar!T x) {}
void main() {
auto x = Bar!int();
f(x);
}
To be sure that I'm not missing anything: You just added the
temporary `x`, right? I don't think that changes anything. The
type of the argument is `Foo!int` in all variations of the code
we've seen, including this one. And that type is all that DMD
sees when it attempts IFTI of `f`.
Ah, I see your point above now (mixing up my Bar!ints and
Bar!Ts). Yes, that was the only change and not really a
substantive change (just my ease of reading).
Your point is basically that a template alias only becomes an
actual alias when it has been instantiated. You then note that
the deduction process operates in terms of Bar (in that you have
to find a T that fits Bar!T to get to an alias of Foo!T). I think
part of what is confusing is that the temporary x in my example
is a Foo!int and not a Bar!int, which is why the Foo!int can't be
passed into f(T)(Bar!T).
I think part of the issue is that many people's mental model
would be for f(T)(Bar!T) to get re-writtn as f(T)(Foo!T), which
is related to Ola's point with respect to type unification.
But the compiler isn't really doing any re-writing, so much as it
sees the Foo!int and does not have the information necessary to
determine that a Foo!int should satisfy Bar!T (as you point out).
It would need to extract int from Foo!int, then instantiate Bar!T
to get Foo!int (which I believe is what the implementation was
doing, or something similar).