chapel
chapel copied to clipboard
Procedures with variadic arguments and following default argument(s) are not properly resolved
When declaring a procedure with variadic arguments and then following with an argument with a default value, the compiler is unable to resolve this. Example below...
proc p(args : int ...?N, defaultArg = true) {
writeln("Success!");
}
p(1);
Note that this will work if the user specifies a value for defaultArg
proc p(args : int ...?N, defaultArg = true) {
writeln("Success!");
}
p(1, true);
As well if more than one argument is passed and if default argument is of type of the variadic function, it works...
proc p(args : int ...?N, defaultArg = 0) {
writeln("Success!");
}
p(1,2,3);
Interesting... thanks for reporting this.
A contributor working on the product iterator from #12657 stumbled across this issue as well:
proc p(args...?n, repeat=1) {
writeln('args: ', args);
writeln('repeat: ', repeat);
}
p('AB', repeat=2); // works
p('AB'); // fails to resolve
Compilation output:
error: unresolved call 'p("AB")'
note: candidates are: p(args ...?n, repeat = 1)
Currently, we can work around this by adding an explicit overload for the default arg(s):
proc p(args...?n, repeat:int) {
writeln('args: ', args);
writeln('repeat: ', repeat);
}
proc p(args...?n) {
p((...args), repeat=1);
}
p('AB', repeat=2); // works
p('AB'); // works now
p('AB', [1,2]); // fails to resolve
It looks to me that this doesn't fail to resolve, but rather it incorrectly binds [1, 2] to repeat rather than to args(2)? Is that not what you're seeing as well? (Try it online)
I seem to have missed the fact that this only impacts the single-argument case. Sorry about that @bradcray. I've updated the example in the original comment to reflect this.
OK, thanks for clarifying and updating. That sounds consistent with the incorrect behavior I was seeing. I.e., if the compiler is trying to bind the last argument to repeat rather than the varargs, yet we don't support 0-tuples / 0-argument calls to varargs functions, it probably won't match unless the call has two or more arguments (where the last can legally match against repeat?).
Can you have overloads that accepts a scalar and one that accepts various non-scalars such as args : [], args : range, etc.?
This one is a toughie. The problem is that the compiler expands var-args before it performs alignment checking (which is wrong). So, it can't distinguish between the p(1, true); and p(1,2) cases, since the number of actuals is the same, and it doesn't know whether true is a vararg actual or if it's a value for the defaulted formal.
Fixing this would require a lot of changes to the way that we handle call resolution (I hit a wall when I realized we need to do rewriting for lifetime checking and where clauses). That said, Dyno seems to support this case just fine. Thus, I think it's best to simply wait for Dyno's resolver to hit production.
Whew! I thought you were describing the dyno resolver in your first paragraph. I completely agree that fixing issues in the production resolver that aren't very simple doesn't make sense at this point, particularly if dyno's got it right.
Associated future tests:
test/distributions/corrado/factoryMethods/typeMethodsBroken.chplwill be added by https://github.com/chapel-lang/chapel/pull/27160