www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2025] New: Inconsistent rules for instantiating templates with a tuple parameter

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025

           Summary: Inconsistent rules for instantiating templates with a
                    tuple parameter
           Product: D
           Version: 2.012
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: samukha voliacable.com


The template with non-tuple parameter is preferred if that parameter is a value
(Case 1). The template with tuple parameter is preferred if the non-tuple
parameter is a type (Case 2).

Case 1
----
template Foo(int i)
{
    pragma(msg, "One");
}

template Foo(A...)
{
    pragma(msg, "Many");
}

alias Foo!(1) foo;
----
Outputs: One

Case 2
----
template Foo(T)
{
    pragma(msg, "One");
}

template Foo(A...)
{
    pragma(msg, "Many");
}

alias Foo!(int) foo;
----
Outputs: Many

Probably both cases should result in an ambiguity error.


-- 
Apr 22 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025


smjg iname.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg iname.com
           Keywords|                            |spec




------- Comment #1 from smjg iname.com  2008-11-21 20:55 -------
This is either wrong-code or accepts-invalid, but we need a clarification in
the spec first.

Compiler behaviour is most certainly wrong in case 2 - it leaves no way to
instantiate the Foo(T) version.


-- 
Nov 21 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla digitalmars.com


--- Comment #2 from Walter Bright <bugzilla digitalmars.com> 2012-01-22
01:30:32 PST ---
Here's what's happening:

Case 1
------
1 is an "exact" match with (int i) and (A...). Since (int i) is more
specialized, it goes with (int i).

Case 2
------
int is a "convert" match with T (so that a better match would be Foo(T:int) and
an "exact" match with (A...). The exact match wins.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 22 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025


timon.gehr gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr gmx.ch


--- Comment #3 from timon.gehr gmx.ch 2012-01-22 12:14:01 PST ---
(T:int) wins against (A...). Why can't the same be done for (T:int) vs (T) ?
(A...) is certainly less specialized than (T), and int matches both equally
well, therefore I think it is strange that (A...) would be chosen over (T).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 22 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #4 from Stewart Gordon <smjg iname.com> 2012-01-31 18:03:36 PST ---
(In reply to comment #2)
 int is a "convert" match with T (so that a better match would be Foo(T:int) and
 an "exact" match with (A...). The exact match wins.
You've lost me here. How is int matching T not exact? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 31 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yebblies gmail.com


--- Comment #5 from yebblies <yebblies gmail.com> 2012-02-01 14:17:20 EST ---
(In reply to comment #4)
 (In reply to comment #2)
 int is a "convert" match with T (so that a better match would be Foo(T:int) and
 an "exact" match with (A...). The exact match wins.
You've lost me here. How is int matching T not exact?
As Walter said, so that T:int would be considered a better match. It is a hack in the compiler that I'm not particularly fond of. See issue 4953 for another case it causes problems. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 31 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #6 from Stewart Gordon <smjg iname.com> 2012-02-01 04:16:53 PST ---
(In reply to comment #5)
 As Walter said, so that T:int would be considered a better match.  It is a hack
 in the compiler that I'm not particularly fond of.
What has a "better match" to do with anything? (int) matches the pattern (T) perfectly - no conversion, implicit or explicit. True, (T: int) is a more specialised match, but that doesn't magically render the match with (T) inexact.
 See issue 4953 for another case it causes problems.
That's different - 5 is an int, so it doesn't exactly match the pattern (short x). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #7 from yebblies <yebblies gmail.com> 2012-02-01 23:32:47 EST ---
(In reply to comment #6)
 What has a "better match" to do with anything?  (int) matches the pattern (T)
 perfectly - no conversion, implicit or explicit.  True, (T: int) is a more
 specialised match, 
 inexact.
 
more specialized == better match. That is how template type deduction works.
 but that doesn't magically render the match with (T)
That's why I called it a hack.
 See issue 4953 for another case it causes problems.
That's different - 5 is an int, so it doesn't exactly match the pattern (short x).
I know it's different, I wrote the patch for it. The hack causes problems there too. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #8 from Stewart Gordon <smjg iname.com> 2012-02-01 04:43:27 PST ---
(In reply to comment #7)
 more specialized == better match.  That is how template type deduction works.
But there's no (T : int) version of this template. We have two templates to match: Foo(T) and Foo(A...). Both patterns match Foo!(int) exactly, and Foo(T) matches a proper subset of everything that Foo(A...) matches. So Foo(T) is the most specialised match that the code has supplied. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #9 from yebblies <yebblies gmail.com> 2012-02-01 23:55:06 EST ---
(In reply to comment #8)
 (In reply to comment #7)
 more specialized == better match.  That is how template type deduction works.
But there's no (T : int) version of this template.
It doesn't matter. The compiler does template argument deduction through a function called matchArg in template.c. It will generate one of the match levels (MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact) based on what the template parameter, spectype, and argument are. matchArg does not know or care what the other overloads of the template are, or even what the other arguments are. For (T : int) to be preferred over (T), it must return a worse match level for the unspecialized parameter. Currently it will return MATCHconvert for these parameters, and return MATCHexact only when there is a (matching) spec type. Which leaves you with a non-exact match for (T) and (T...), even if it's the only overload. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #10 from Stewart Gordon <smjg iname.com> 2012-02-01 05:27:34 PST ---
(In reply to comment #9)
 For (T : int) to be preferred over (T), it must return a worse 
 match level for the unspecialized parameter.  Currently it will 
 return MATCHconvert for these parameters, and return MATCHexact 
 only when there is a (matching) spec type.
So MATCHexact means "the pattern can be matched only by this exact set of arguments", and MATCHconvert means "this is one of various sets of arguments that can match this pattern". But then, surely, it would be rejecting the instantiation as ambiguous, not picking the (A...) overload. Really, it's a fundamental flaw in the compiler logic whereby it conflates two essentially orthogonal concepts: exactness and specialisation. A correct template instantiation algorithm would: - see which template patterns match the instantiation exactly - if none, see which template patterns match with implicit conversions - of all the matches, determine which is most specialised -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #11 from yebblies <yebblies gmail.com> 2012-02-02 00:42:20 EST ---
(In reply to comment #10)
 So MATCHexact means "the pattern can be matched only by this exact set of
 arguments", and MATCHconvert means "this is one of various sets of arguments
 that can match this pattern".
 
No, MATCHconvert means 'match with implicit conversions'. These are the same match levels used for normal function argument matching.
 But then, surely, it would be rejecting the instantiation as ambiguous, not
 picking the (A...) overload.
 
Actually, (A...) is an alias parameter so it comes up as MATCHexact. (There is a bug report about this somewhere). Otherwise you would get an ambiguity error. This is not what should be happening, non-variadic templates should be preferred over variadic ones.
 Really, it's a fundamental flaw in the compiler logic whereby it conflates two
 essentially orthogonal concepts: exactness and specialisation.
 
 A correct template instantiation algorithm would:
 - see which template patterns match the instantiation exactly
 - if none, see which template patterns match with implicit conversions
 - of all the matches, determine which is most specialised
It's not that simple when you take multiple parameters, overloads, mixing explicit template parameters and deduced ones, etc The ordering (exact match, const match, convert match, deduced match, variadic match, alias match, specialized match, etc) is complicated and the match system needs a redesign to cope with it. Expanding the current match system will not necessarily solve the problem, as the different levels interact in weird ways. This is probably what will end up happening if a better solution is not found. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #12 from Stewart Gordon <smjg iname.com> 2012-02-01 06:39:13 PST ---
(In reply to comment #11)
 No, MATCHconvert means 'match with implicit conversions'.  These are the same
 match levels used for normal function argument matching.
int is a type. T as a template parameter denotes exactly that - a type. So what implicit conversion is being performed? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2025



--- Comment #13 from yebblies <yebblies gmail.com> 2012-02-02 01:51:55 EST ---
(In reply to comment #12)
 (In reply to comment #11)
 No, MATCHconvert means 'match with implicit conversions'.  These are the same
 match levels used for normal function argument matching.
int is a type. T as a template parameter denotes exactly that - a type. So what implicit conversion is being performed?
None. That's why it's a hack to use it to represent deduced args with no spec type. That's why it causes problems... If you really want to understand how dmd does template deduction and overload matching have a poke around in template.c (deduceFunctionTemplateMatch and matchArgs) and mtype.c (callMatch). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2012