New Issue: Feature request: isIterable() and canBePromoted()

19261, "vasslitvinov", "Feature request: isIterable() and canBePromoted()", "2022-02-17T00:04:02Z"

This issue requests the ability to encode promotion in the source code.

For example, within a generic function I might want to check whether myFun(arg1, arg2) is a legal promoted expression and execute that promotion if so.

I want to use this feature when I want to:

  • define an operation as a generic function with fully-generic formals, and
  • dispatch to an appropriate implementation using param conditionals within the body of the function.

The implementation proposal in #19254 gives an idea of this context. There, it works without this feature because its goal is to disallow promotion.

Consider this example:

proc myPlus(a, b) {
  if ! isNumeric(a) then
    compilerError("illegal");
  if isNumeric(b) {
    return a + b;
  } else if canBePromoted(myPlus(a,b)) {
    return [bElm in b] myPlus(a, bElm);
  } else {
    compilerError("illegal");
  }
}

except instead of isArray(b) I'd like to inquire whether b is something that I can promote myPlus over.

Why do I want to this coding style instead of defining multiple overloads?

  • All legal and illegal cases are together in one place.
  • I can control which arguments to promote and which not to, assuming that canBePromoted() gives me that power.
  • I can issue a simple message like "myPlus(string, real)" is not legal, instead of saying "myPlus(string, real) is not resolved, here are NN unsuccessful candidates". Which may be preferable if this is a library function.
  • If somebody wants to add a special case of myPlus later, they can, and the resolution will favor it over my fully-generic overload.

An open question is how to define canBePromoted(). For the above example and a call canBePromoted(myPlus(int, array of string)), the compiler might want to apply the usual promotion rules and reduce it to myPlus(int, string), then realize that it is illegal because myPlus(int, string) produces a compilerError.