18817, "mppf", "should type constructors participate in function disambiguation?", "2021-12-08T19:21:30Z"
PR #18700 implemented a pattern in the compiler/next resolver that needs more discussion.
For a generic class or record type, the compiler generates a type constructor. This process is described in Generics — Chapel Documentation 1.25 . In the spec, the type constructor is described as a function that the compiler is generating. That led me to thinking that this generated function should participate in overload resolution along with other functions.
Here is a specific example that we can consider:
record R {
type t;
}
{
proc R(arg: int) {
return arg;
}
var x = R(arg=1); // trying to call proc R above
var y:R(t=real); // trying to call the type constructor
}
What we get today when we try to compile this program is this error:
bb.chpl:11: error: unresolved call 'R(t=type real(64))'
bb.chpl:6: note: this candidate did not match: R(arg: int)
bb.chpl:11: note: because call uses named argument t
bb.chpl:6: note: but function contains no formal named t
Notably, this error message does not say anything about ambiguity or shadowing. At first I thought that this error might have come about as a result of #13315 but testing with 1.19 which should be before that PR shows similar behavior.
Here is another example that doesn't use an inner scope:
record B {
param p;
}
proc B(type t) type { // maybe this is desired as a convenience
return B(0:t);
}
var x: B(1); // trying to call type constructor
var y: B(int); // trying to call type returning function
Today, this fails to compile with:
cc.chpl:1: error: 'B' has multiple definitions, redefined at:
cc.chpl:4
This issue is asking if either of these program should compile - and if not, what the error message should be indicating.
Arguments in favor of them compiling:
- it's convenient to describe the type constructor as an automatically generated type-returning function; the spec does that today; and this description would imply that the generated function will be resolved the same as other functions
- if a generic record changes which fields are generic, then code doing type construction of that record will need to change too. Being able to add a regular type-returning function overload can help library authors to support backwards compatibility and deprecation.
Arguments against them compiling:
- if there is both a
proc R
and arecord R
, then use of the recordR
would be ambiguous with capturing the functionR
unless we introduce an idea that the name resolution depends on how the name is used. (More broadly, a variable can be called syntactically, sincemyVar(i)
runs the.this
function, so it would be challenging to disambiguatemyVar(i)
in the presence of a.this
as well as aproc myVar
).
This issue is tangentially related to #18177 in that paren-less and paren-full methods with the same name in the same scope might be viewed as a similar idea.