16415, “vasslitvinov”, “Visibility rules for methods”, “2020-09-18T06:00:51Z”
When is the method Bar.doSomething()
visible from a call site?
Basic cases
(Rule A - lexical scoping) doSomething() is defined in the same or lexically-enclosing scope. Can be public
or private
. This is the same as for non-methods. Status: agreed on.
(Rule B - unrestricted use
) doSomething() is public
or re-exported by a module whose use
is visible from the call site. This is the same as for non-methods. Status: agreed on.
(Rule C - visible from Bar definition) doSomething() is public
and visible from the definition of Bar. For example, it is a primary method on Bar or a secondary method defined in the same scope as Bar. Status: agreed on.
(Rule D - always) doSomething() is defined as a method on Bar anywhere in the program. Option: must be public
. Example: UserOfBar1
here. Status: open - requested by Brad, opposed by Vass.
(Rule E - visible from producer) doSomething() is public
and visible from the definition of the function that produced the Bar receiver, ex. (producer()).doSomething()()
. Status: no supporters.
Third-party definitions
How to bring in a method from a “third-party” module, i.e. other than where Bar is defined?
We are looking to choose some of the options below. This is a summary of the discussion in #16357. Reasoning is partly motivated by Brad’s analogy between a method and a symbol within a module here. We start with Michael’s example:
module DefinesBar {
record Bar { }
}
module DefinesBarMethod {
use DefinesBar;
proc Bar.doSomething() { }
}
module ReturnsBar {
proc makeBar() {
use DefinesBar;
return new Bar();
}
}
module UserOfBar2 {
import ReturnsBar;
var x = ReturnsBar.makeBar();
// How to allow 'x.doSomething()' below to compile?
// Options:
use DefinesBarMethod; // (Rule B - unrestricted use)
use DefinesBarMethod only; // (Rule F - empty only)
use DefinesBarMethod only Bar; // (Rule G - type brings its methods)
use DefinesBarMethod only doSomething; // (Rule H - symbols include methods)
use DefinesBarMethod only Bar.*; // (Rule I - dot star)
use DefinesBarMethod only Bar.doSomething; // (Rule J - dot name)
x.doSomething();
}
Illustrated in the code above:
(Rule F - empty only
) use DefinesBarMethod only
makes doSomething() visible.
Status: generally opposed.
(Rule G - type brings its methods) only Bar
makes all methods on Bar also visible.
Status: this is a key feature under discussion.
(Rule H - symbols include methods) only doSomething
applies to all symbols including methods.
Status: mostly opposed.
(Rule I - dot star) Bar.*
specifies all methods of the type Bar. Option: includes the type Bar itself.
Status: replacement or (future) addition to Rule G.
(Rule J - dot name) Bar.doSomething
specifies methods with the specific name.
Status: (future) addition.
Additionally:
(Rule P - applies only to public
) Rules (G)…(J) additionally require that doSomething() be public. Private methods cannot be accessed outside their module.
Status: generally agreed on.
(Rule R - requires re-export) Rules (G)…(J) additionally require that Bar be re-exported by the third-party module DefinesBarMethod.
Status: uncertain.
While above we discuss only the only
clause, the same rules apply to import
and (with the opposite meaning) to except
.
Other
The POI rule and dynamic dispatch / virtual methods are not discussed here.
Special methods – the visibility rules are to be discussed separately for:
init
init=
deinit
=
(assignment)
op=
How to handle punctuation-based operators like +
?