16584, “vasslitvinov”, “Visibility of “tertiary” methods?”, “2020-10-13T23:24:59Z”
A method is always visible if it is public and is declared in the lexical scope where the type is declared, according to our visibility rules. This includes both primary and secondary methods. The rationale is that those are made by the type author, so they are “part of the type”.
How about “tertiary” methods, i.e. secondary methods declared outside of the type definition’s module, “after the fact,” so to speak? For example:
module Rdef {
record R {}
proc R.secondary() { }
}
module Rter {
use Rdef;
proc R.tertiary() { }
}
/* This module provides an enhanced version of 'R'. */
module Rmake {
use Rdef, Rter;
proc makeR() {
return new R();
}
}
use Rmake;
makeR().secondary(); // always visible
makeR().tertiary(); // also visible?
The motivation for allowing makeR().tertiary()
is that the author of makeR
explicitly wants to make tertiary()
available to its users.
The primary challenge with allowing this idiom is its use in third-party libraries, for example:
module Library {
proc drawme(arg) {
writeln(arg.secondary());
writeln(arg.tertiary());
}
}
module User {
use Rmake, Library;
drawme(makeR());
}
Another challenge is mixing R
instances from different sources, ex.:
module Rmake2 {
.... R and a different proc R.tertiary() are visible ....
proc makeR2() return new R();
}
module User {
use Rmake, Rmake2, Library;
drawme(if condition() them makeR() else makeR2());
}
The leading solutions (exluding the “mixing” scenario) are:
(WR) Have makeR()
return a wrapper record that defines tertiary()
and forwards the rest to R
. Cons: lost type equality between the result of makeR() and R.
(CG) Have drawme()
use constrained generics, requiring tertiary()
on its argument. Cons?