19352, "mppf", "How does do methods only from the type definition point interact with shadowing?", "2022-03-04T14:46:45Z"
For https://github.com/Cray/chapel-private/issues/2690
This issue is asking a question about how the rule to find visible functions from the method's definition point interacts with shadowing. #16415 summarizes the current design which was implemented in PR #16208. PR #16976 implemented a related feature where use SomeModule.someType
or import SomeModule.someType
will bring in methods defined on someType
from that module.
For the most part, the current behavior seems to be similar to the type's definition point being a last place to look if nothing else is found. In other words, methods available locally or via a use
statement will always shadow methods available only from the type's definition point. I do not view the current situation as an obvious combination of other ideas but it is something we could keep and then document.
The remainder of this issue discusses a few specific examples. In these examples, we will assume this is the start of the program:
module Library {
record rec {
proc method() { writeln("Library's rec.method()"); }
}
}
module LibraryPlus {
import Library;
import Library.rec;
proc rec.method() { writeln("LibraryPlus's rec.method()"); }
}
Case 1: Can Import of a Type Cause Shadowing?
First, even after PR #19306, the import SomeModule.someType
does not seem to shadow at all. Arguably it should, but maybe an ambiguity error is bettor for hijacking scenarios.
// Case 1
module Program {
import Library;
proc main() {
import LibraryPlus.rec; // does this make LibraryPlus.rec.method "closer" ?
var r = new Library.rec();
r.method(); // currently: ambiguity error
}
}
Case 2: Should Type's Definition Point be Shadowed?
How should methods brought in from the type's definition point interact with a method defined locally? Today the local method shadows the ones from the definition point.
// Case 2a
module Program {
import Library;
import Library.rec; // Should this bring in the methods as if defined here?
proc rec.method() { writeln("Program's rec.method()"); }
proc main() {
var r = new Library.rec();
r.method(); // currently outputs: Program's rec.method()
}
}
// Case 2b
module Program {
import Library; // Should this bring in the methods
// on types defined in Library as if defined here?
proc (Library.rec).method() { writeln("Program's rec.method()"); }
proc main() {
var r = new Library.rec();
r.method(); // currently outputs: Program's rec.method()
}
}
Case 3: Should a Use Statement Cause Shadowing?
Should a method available via a use
statement always shadow methods available only from the type's definition point? Arguably, it would be better for this to be an ambiguity error, to prevent a hijacking scenario.
module Program {
public import Library;
public use LibraryPlus; // should LibraryPlus.rec.method now shadow Library.rec.method?
proc main() {
var r = new Library.rec();
r.method(); // currently:
// without PR #19306, ambiguity error
// with PR #19306, outputs LibraryPlus's rec.method()
}
}
Interaction with Adding a Method
If Library
didn't have method
but Program
did have one, then when Library
adds one it will be shadowed by the Program
version (non-breaking). That seems OK.
However, when Program
depends on both Library
and LibraryPlus
and these add method
in one order or another, I don't see how it is possible to keep that method addition as a non-breaking change to Program
.
If Library
didn't have method
but LibraryPlus
added it, then when Library
adds one it will currently be an ambiguity error (Case 1) (breaking) or will be shadowed by the LibraryPlus
version (Case 3) (non-breaking). If we changed it to be shadowed by the Library
version, it would be worse (breaking / hijacking).
If Library
has method
but LibraryPlus
didn't, and then LibraryPlus
adds one, it will currently be an ambiguity error (Case 1) (breaking) or it will will be shadowed by the LibraryPlus
version (Case 3) (breaking / hijacking).
So, arguably, it would be better for Case 1 and Case 3 to be ambiguity errors, since if we prefer one or the other for shadowing, that introduces the possibility of surprising behavior changes when a method is added. At least the ambiguity errors would point out that there is a potential problem.