March 14, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #29 from timon.gehr@gmx.ch 2013-03-14 15:56:33 PDT ---
(In reply to comment #28)
> (In reply to comment #26)
> 
> It's not about the polysemous literals.
> What's irritating me is that a function call with conversion
> is preferred over a function template instantiation with
> exact arguments.
> 
> int f3(long) { return 1; }
> int f3(T)(T) { return 2; }
> 
> int v = 2;
> f3(v);
> 
> MATCHexact / MATCHconvert vs.
> MATCHconvert / MATCHexact

IMO the second should be MATCHexact / MATCHexact.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 15, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #30 from Kenji Hara <k.hara.pg@gmail.com> 2013-03-15 07:27:23 PDT ---
(In reply to comment #29)
> (In reply to comment #28)
> > (In reply to comment #26)
> > 
> > It's not about the polysemous literals.
> > What's irritating me is that a function call with conversion
> > is preferred over a function template instantiation with
> > exact arguments.
> > 
> > int f3(long) { return 1; }
> > int f3(T)(T) { return 2; }
> > 
> > int v = 2;
> > f3(v);
> > 
> > MATCHexact / MATCHconvert vs.
> > MATCHconvert / MATCHexact
> 
> IMO the second should be MATCHexact / MATCHexact.

No. type parameter deduction is less specialized than matching to explicitly specialized type parameter.

void foo(T)(T) {}      // generic version
void foo(T:int)(T) {}  // specialized to int

foo(1);  // calls T:int version

That is why f3(v) makes MATCHconvert / MATCHexact with template version.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 15, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #31 from timon.gehr@gmx.ch 2013-03-15 15:52:59 PDT ---
(In reply to comment #30)
> ...
> Parameter deduction is less specialized than matching to explicitly
> specialized type parameter.
> ...

It's not less specialized than a normal function call without type parameters. A type parameter should match a type argument exactly.

Specialization mustn't be confused with the matching level -- it should be checked in a second step, as is done for functions.

Why?: Specialization is a partial order, while the matching levels form a full order. There is no way to correctly implement specialization only by abusing matching levels.

(At the very least, the logic for template specialization should not interfere with template vs. function overloading!)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 15, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #32 from Kenji Hara <k.hara.pg@gmail.com> 2013-03-15 16:51:36 PDT ---
(In reply to comment #31)
> (In reply to comment #30)
> > ...
> > Parameter deduction is less specialized than matching to explicitly
> > specialized type parameter.
> > ...
> 
> It's not less specialized than a normal function call without type parameters. A type parameter should match a type argument exactly.
> 
> Specialization mustn't be confused with the matching level -- it should be checked in a second step, as is done for functions.
> 
> Why?: Specialization is a partial order, while the matching levels form a full order. There is no way to correctly implement specialization only by abusing matching levels.
> 
> (At the very least, the logic for template specialization should not interfere with template vs. function overloading!)

I talked the expected behavior by using the words used in dmd implementation. Yes, MATCH(exact|const|convert|nomatch) might not be the best word to talk language specification. But it is not a true problem.

Essentially the thing I talking is:

void foo(int) {}       // 1
void foo(T:int)(T) {}  // 2
void foo(T)(T) {}      // 3
foo(1);

Non template function (1) is specialized _as same as_ explicitly specialized
template function (2). Then, normally deduced template function is less
specialized than (1) and (2).

My patch represents the specialization order for IFTI by the pair of MATCH value. And, (3) is represented by MATCHconvert / MATCHexact internally.

Do not confuse internal representation and expected language specification/behavior.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 07, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #33 from Andrei Alexandrescu <andrei@erdani.com> 2013-04-07 07:33:07 PDT ---
Great thread. Sorry I'm late to it! Let me make an appeal to simplicity - even if we come up with a very meaningful and consistent set of overloading rules, we lose if they are complicated. Simplicity is very important for figuring out what function will be called in a context.

In that spirit I'd like to propose a basic strategy as follows:

1. Define a SIMPLE partial ordering relation <= between functions called "at least as specialized" (and correspondingly a strict version < meaning "more specialized").

2. Whenever two or more functions match a call, there is a "winner" only if it is more specialized than all other candidates. (Not all candidates must be partially ordered among themselves, but the winner must be more specialized than all others.) Otherwise, there is ambiguity.

Now for the simple partial ordering relation: consider a call to a function
fun(args) with two overloads fun1 and fun2 that would accept the arguments,
i.e. fun1(args) and fun2(args) would both compile in isolation.

To decide whether fun1 and fun2 are partially ordered, we look at the sets of accepted arguments. If fun2 accepts any argument fun1 would accept, we write fun1 <= fun2 and we say "fun1 is at least as specialized as fun2" or "fun2 is not more specialized than fun1".

Now, if fun1 <= fun2 and fun2 <= fun1 then the two are "as specialized" so a decision cannot be made between the two. If only one of the relations applies, then one of them is strictly more specialized and it is preferred in an overloaded call. If neither relation applies, the functions are unordered so again a decision cannot be made.

On the examples given by Kenji:

    int f1(int a, double=10) { return 1; }
    int f1(int a, string="") { return 2; }

These functions are not ordered because e.g. f1(2, 3.4) would not be accepted
by the second overload and f1(2, "hello") would not be accepted. So the call
f1(5) is ambiguous.

    int f2(T:int)(T b, double=10) { return 1; }
    int f2(T:int)(T b, string="") { return 2; }

Same here, these overloads are not ordered.

    // vs deduced parameter
    int f3(int a) { return 1; }
    int f3(T)(T b) { return 2; }

Here the second overload accepts f3("hello") so the first overload is more
specialized. It will be preferred even in calls with an implicit conversion,
e.g. f3(cast(short) 42). THIS IS A DEPARTURE FROM C++'S RULES.

    // vs specialized parameter
    int f4(int a) { return 1; }
    int f4(T:int)(T b) { return 2; }

These two functions are in the same equivalence classes because they accept the same argument sets: f4_1 <= f4_2 and f4_2 <= f4_1. So any call that would match these two would be ambiguous.

    // vs deduced parameter + template constraint (1)
    int f5(int a) { return 1; }
    int f5(T)(T b) if (is(T == int)) { return 2; }

The constraint is evaluated first and then "disappears" leaving two functions. Of these, the non-template is more specialized.

    // vs deduced parameter + template constraint (2)
    int f6(int a) { return 1; }
    int f6(T)(T b) if (is(T : int)) { return 2; }

Same here. Given that the constraints are arbitrary Boolean expressions, we can't make good estimates on what sets of arguments they'll match.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 08, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #34 from Kenji Hara <k.hara.pg@gmail.com> 2013-04-07 18:44:04 PDT ---
(In reply to comment #33)
[snip]

That's the rule described in TDPL. I can completely agree with you. I believe that my patch implements it enough.

----

I'd like to add one note for your better understand.

>     // vs specialized parameter
>     int f4(int a) { return 1; }
>     int f4(T:int)(T b) { return 2; }
> 
> These two functions are in the same equivalence classes because they accept the same argument sets: f4_1 <= f4_2 and f4_2 <= f4_1. So any call that would match these two would be ambiguous.

That's true if and only if one int argument is given. In D, the template specialized parameter (T:int) means "T should exactly matches to int".

  int fx(T:int)(T b) { return 2; }
  void main() { fx(1L); }

  test.d(2): Error: template test.fx does not match any function template
declaration. Candidates are:
  test.d(1):        test.fx(T : int)(T b)
  test.d(2): Error: template test.fx(T : int)(T b) cannot deduce template
function from argument types !()(long)

So, f4 would match to non-template version if a non-int argument is given.

  assert(f4(1L) == 1);   // not ambiguous

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 08, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #35 from Andrei Alexandrescu <andrei@erdani.com> 2013-04-07 19:13:35 PDT ---
@Kenji: My bad, I forgot T:int means exact match, thought it's match with conversion. (BTW that's a mistake: The syntax in classes suggests that class T:U means subtyping. But it's too late to fix that now.)

So, you're right. Thanks for the clarification! Have you linked a pull request yet?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 08, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528


Kenji Hara <k.hara.pg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull


--- Comment #36 from Kenji Hara <k.hara.pg@gmail.com> 2013-04-07 19:28:23 PDT ---
(In reply to comment #35)
> @Kenji: My bad, I forgot T:int means exact match, thought it's match with conversion. (BTW that's a mistake: The syntax in classes suggests that class T:U means subtyping. But it's too late to fix that now.)
> 
> So, you're right. Thanks for the clarification! Have you linked a pull request yet?

Oh, I forgot to add 'pull' tag. Will do.

URL is already in comment #9, but I re-post it here. https://github.com/D-Programming-Language/dmd/pull/1409

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 28, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #37 from github-bugzilla@puremagic.com 2013-06-28 12:17:44 PDT ---
Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/edd0f6fbeeff70eccd7d2e15429b20418360eca5 fix Issue 1528 - [tdpl] overloading template and non-template functions

- Improve `resolveFuncCall` for integrated function call resolution.
  All of error reporting is done in here.

- Remove `overloadResolve` and `deduceFuncitonTemplate`
  The works was in `overloadResolve` are moved to `resolveFuncCall`,
  and things was in `deduceFuncitonTemplate` are divided to
  `templateResolve` and `resolveFuncCall`.

- Change the name from `overloadResolveX` to `functionResolve`
  It is paired with `templateResolve`.

- Decide 'most specialized' function based on the two `MATCH` values derived
from `tiargs` and `fargs`.
  With non template functions, `last matching level for tiargs` is treated as
`MATCHexact`.

----
The bug that is fixed at the same time:
fix Issue 9596 - Ambiguous match is incorrectly hidden by additional lesser
match

  The change in test/runnable/template9.d is related.

https://github.com/D-Programming-Language/dmd/commit/fba440cc7dc1210b0450f8b01d18661ebbd0da55 Merge pull request #1409 from 9rnsr/fix1528

Issue 1528 - [tdpl] overloading template and non-template functions

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 28, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=1528


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #38 from bearophile_hugs@eml.cc 2013-06-28 14:16:04 PDT ---
(In reply to comment #37)
> Commits pushed to master at

This is a significant improvement.

I am testing this feature a little. This is code reduced from your Comment 10:


int f1(int a, double=10) { return 1; }
int f1(int a, string="") { return 2; }
int f2(T:int)(T b, double=10) { return 1; }
int f2(T:int)(T b, string="") { return 2; }
void main() {
    f1(1);
    f2(1L);
}


It gives the errors:

test.d(6): Error: called with argument types:
    (int)
matches both:
    test.d(1): test.f1(int a, double _param_1 = 10.0000)
and:
    test.d(2): test.f1(int a, string _param_1 = "")
test.d(7): Error: template test.f2 does not match any function template
declaration. Candidates are:
test.d(3):        test.f2(T : int)(T b, double = 10)
test.d(4):        test.f2(T : int)(T b, string = "")
test.d(7): Error: template test.f2(T : int)(T b, double = 10) cannot deduce
template function from argument types !()(long)


For the error at line 6 it nicely indents the lines test.d(1) and test.d(2).

While for the error at line 7 it doesn't indent the lines test.d(3) and
test.d(4).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------