Opened 11 months ago

#225 new defect

Wrong disambiguation for call overloaded on bare type-variable vs generic

Reported by: mlbrooks Owned by:
Priority: major Component: cfa-cc
Version: 1.0 Keywords:
Cc:

Description

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.

Change History (0)

Note: See TracTickets for help on using tickets.