18081, "mppf", "Problem with instantiation caching for different POIs", "2021-07-20T17:21:39Z"
(See also PR #16261 and issue #16261)
As of 1.23, the compiler tries to provide a behavior that caching of instantiations does not change program behavior.
However this is not the case with the following program:
module G {
proc foo(param arg:int, val:int) { // "int variant"
bar(arg);
}
proc foo(param arg:int, val:real) { // "real variant"
bar(arg);
}
}
module M1 {
use G;
proc bar(arg: int) {
writeln("In M1.bar ", arg);
}
proc runM1() {
writeln("In runM1");
foo(1, 20);
}
}
module M2 {
use G;
proc bar(arg: int) {
writeln("In M2.bar ", arg);
}
proc runM2() {
writeln("In runM2");
foo(1, 20.0);
}
}
module User {
use M1, M2;
proc main() {
runM1();
runM2();
}
}
Current program output:
In runM1
In M1.bar 1
In runM2
In M1.bar 1
Expected program output:
In runM1
In M1.bar 1
In runM2
In M2.bar 1
I came across this when thinking about the structure of function resolution in the compiler rework.
What I think is happening here is that the instantiation caching strategy relies on the function body being resolved. In this particular program, within runM1
, the signatures of both versions of foo
are resolved, but only the body of the int variant is resolved. As a result, the CalledFunInfo
entries are not gathered yet. Then, in runM2
, when considering if the existing instantiation of the real variant of foo
can be reused, the compiler concludes that it can be reused because there were no CalledFunInfo
to rule it out.
Reasonable fixes might be to:
- forget that the function signature for the real variant of
foo
was created inrunM1
since it wasn't used anyway; or - when considering reusing the real variant of
foo
inrunM2
, the compiler can fully resolve that function (in order to be able to make a determination of whether or not it can be reused in the current case). Note that if this strategy is chosen, the compiler will need to be able to hide any errors encountered when resolving the body of the real variant offoo
(since that version is actually never called in the program).