20279, "ghbrown", "Confusing sort behavior when comparator defines duplicate methods due to canResolveMethod behavior", "2022-07-20T19:29:42Z"
Summary of Problem
The sort module can exhibit some confusing (to users) behavior if the comparator has multiply defined methods. For example, in the code below, when the compare
method is only defined once, the sort uses compare
. However, if the comment inside sort_wrap
is removed then compare
is defined twice, but the sort uses keyPart
instead of compare
.
This was extremely puzzling at first. I expected that I would either get an error for the multiple definition of compare
, or I would be able to "overwrite" it and the second compare would be used.
@mppf and @bradcray found the cause of the behavior, the use of the reflection method Reflection.canResolveMethod
in the sort module. When the method in question can't be resolved (like when there are multiple definitions) it silently falls back to another comparison method without warning or error.
We've talked about this in the Discourse thread (long, touches on multiple unrelated issues) and thought this issue could be a place to discuss similar problems, as well as possible "fixes" to this somewhat rare edge case.
I'm copying over a couple of Brad's thoughts from the thread:
Maybe the approach would be to have the sort module do something before falling back like seeing whether there are any methods named '.key' or seeing how many candidates there are for the call and issuing an error if there are more than one. Or maybe canResolve() needs to be redesigned in some way [maybe to give more information].
Steps to Reproduce
use Sort;
record comparator_def {
proc keyPart(a,i) {
writeln('keyPart');
return defaultComparator.keyPart(a,i);
};
}
proc sort_wrap(Data : [?Dom] ?eltType) {
proc comparator_def.compare(a,b) {
writeln('compare 1');
if (a > b) {
return 1;
} else if (a == b) {
return 0;
} else {
return -1;
}
}
//proc comparator_def.compare(a,b) {
// writeln('compare 2');
// if (a > b) {
// return 1;
// } else if (a == b) {
// return 0;
// } else {
// return -1;
// }
//}
sort(Data,comparator=new comparator_def());
}
var a = [1,1,20,4,-5,2,3,111,12,5,100];
sort_wrap(a);
writeln(a);
Compile command:
chpl
Configuration Information
using packaged version on Arch Linux
chpl version 1.28.0 pre-release (c95e180325)
built with LLVM version 14.0.6