﻿id	summary	reporter	owner	description	type	status	priority	component	version	resolution	keywords	cc
225	Wrong disambiguation for call overloaded on bare type-variable vs generic	mlbrooks		"Overload selection fails to pick the most specific option, when choosing, for a parameter, between T and thing(T).

{{{
forall( dtype T )
void friend( T & ) {
    printf(""friending generically\n"");
}

forall(dtype T)
struct thing {
    int x;
};

forall( dtype T )
void friend( thing(T) & ) {
    printf(""friending specifically\n"");
}

int main() {
    float x;           friend( x );
    thing(float) y;    friend( y );
}
}}}

Actual output:
{{{
friending generically
friending generically
}}}

Expected output:
{{{
friending generically
friending specifically
}}}

Selecting in the expected way is required to support the in-progress design for multidimensional array slices.  This slicing is facilitated by a `packed` structure, which represents objects arranged with nontrivial striding.  The design aims to offer subscripting that appears the same, between traditional arrays, and those that involve `packed` elements.  So the design needs to offer one subscript operator on ""array of T"", and a specialized one on ""array of packed of T"".  The above repro scenario is a simplification of this requirement.

If overload selection stays as Actual, then a subscript that should look like
{{{
a[u][v][w][x][y][z]
}}}
has to use a workaround like
{{{
a[u]`unpack[v][w][x]`unpack[y][z]
}}}
where the locations of the required unpack calls are hard for a user to understand, and are meant to be implementation-hidden.

Some white-box observations about the simple repro:

The call `friend(y)` considers the two alternatives following, as expected.  Their costs are at issue.
{{{
friend: void (*)( T )          [ thing(float) / T ]   ( 0, 1, 0, 0, 1, -1, 1 )   ""opt 1""
friend: void (*)( thing( T ) ) [ float / T ]          ( 0, 1, 0, 0, 1,  0, 1 )   ""opt 2""
}}}

The cost tuples are formatted ( _, poly, _, _, var, spec, _ ), which are documented in Cost.h as:
- poly: Count of parameters and return values bound to some poly type
- var: Count of polymorphic type variables
- spec: Polymorphic type specializations (type assertions), negative cost

The difference between actual and expected behaviour has two levels:

First, why isn't option 2 preferred over option 1?
- ""Actual"" perspective: because the poly and var elements are equal.
- ""Expected"" perspective: they should differ on the poly element, because this is the only element that considers a count of parameters, and we are lookaing at one parameter, where calling it a T is strictly more general than calling it a thing(T)

Second, assuming option 2 isn't preferred, why aren't the options reported as ambiguous?
- ""Actual"" perspective: because the spec elements are different.
- ""Expected"" perspective, for this issue: don't really care
- Long-term perspective: there may be a further bug illustrated here; the code that credits -1 for option 1 is doing so on account of the parameter being a reference (which is dubious, given the stated mission to count assertions), yet this code counts the reference-as-specialization benefit differently for T& vs thing(T)&.  Changing the example to pass otypes by value (so T vs thing(T)) gives ambiguous resolution (with spec=-4).

This does not seem to be the same ambiguity as #194, where there, the desired resolution is in the last-place reference-cost element.

Potential overlap with #195 should be assessed further.
"	defect	new	major	cfa-cc	1.0			
