cat > bug.d << CODE struct Pair(T1, T2) {} template foo(T : Pair!(T, U), U) { pragma(msg, "foo ", T, U); } template bar(T : Pair!(T, U), U:int) { pragma(msg, "bar ", T, U); } static assert(!__traits(compiles, foo!(Pair!(double, short), int))); // OK static assert(!__traits(compiles, bar!(Pair!(double, short), int))); // fails CODE dmd -c bug -------- For bar the argument to U is ignored and U is deduced from Pair.
cat > bug.d << CODE struct Pair(T1, T2) {} template foo(T : Pair!(T, U), U) { enum val = 0; } template foo(T : Pair!(T, U), U:int) { enum val = 1; } static assert(foo!(Pair!(int, int)).val == 1); // FAIL - matches both static assert(foo!(Pair!(int, short)).val == 1); // FAIL - matches the first static assert(foo!(Pair!(int, float)).val == 0); // OK - matches the first CODE dmd -c bug -------- This also behaves incorrect for specialized overloads.
The code example in [1] now compiles successfully, as it should. The code example in [2] fails the first 2 asserts. That is the correct behavior IMHO. The first and second Pair instantiations match both overloads and the third one matches a single template (the one that is not specialized on U). What else could be the correct behavior? For example, in [1], both: static assert(__traits(compiles, foo!(Pair!(double, short), short))); static assert(__traits(compiles, bar!(Pair!(double, short), short))); and static assert(__traits(compiles, foo!(Pair!(double, int), int))); static assert(__traits(compiles, bar!(Pair!(double, int), int))); compile successfully. Closing as WORKSFORME. Please reopen if I am missing something. [1] https://issues.dlang.org/show_bug.cgi?id=7686#c0 [2] https://issues.dlang.org/show_bug.cgi?id=7686#c1