<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<br>
<br>
<blockquote type="cite"
cite="mid:CAC1Wh8ErVgE3JpJGCrwmg=XO77pz0iRfap2PgivCN--NS91omA@mail.gmail.com">
<div dir="ltr">
<div>Two remarks. First, I'm not sure what you mean by "static
lambda". Of course it is already possible for a lambda to be
declared as a static member of some class (static Runnable r =
() -> {};), so you must mean something else, but I don't
know what that is. Do you imagine a special declaration mode
for a lambda that asks the compiler to ensure that it captures
nothing?</div>
</div>
</blockquote>
<br>
Not that I am saying Java needs these, but ...<br>
<br>
Lambdas can capture effectively final locals; those that happen to
not do so are translated differently (the instance is cached at the
capture side, so have better performance characteristics.)Â Thing is
an example of the compiler _inferring_ that the lambda could have
been "static" (captures nothing from its context). But the flip
side is where the author would _declare_ that the lambda _cannot_
capture anything. This guarantees the better translation, but also
gets better type chekcing -- if the author mistakenly captures
something, they get a compiler error, rather than slower
performance. So this is what I mean by a "static lambda" -- a
lambda that is declare to _not be allowed_ to capture anything. <br>
<br>
It gets worse with anon classes, because we don't even do the
inference and the better translation there when we can, and not
capture the enclosing instance when it doesn't get used, causing
more footprint and potentially unintended retention. <br>
<br>
<blockquote type="cite"
cite="mid:CAC1Wh8ErVgE3JpJGCrwmg=XO77pz0iRfap2PgivCN--NS91omA@mail.gmail.com">
<div dir="ltr">Second, how do code-containing constructs which are
not methods or classes fit into this? I have field initializers
in mind, but maybe static/instance initializers are relevant
too. Does it make sense to nest a method inside of an instance
initializer? <br>
</div>
</blockquote>
<br>
For purposes of the capturing rules, field initializers for {
static, instance } fields should be treated as nested { static,
instance } methods, and similar for { static, instance }
initializers. <br>
<br>
The question of whether to _allow_ local methods in these things is
a separate story; there is a pro (consistency) and a con (ugh,
really?) argument to be made there, but if we did, the capture rules
would follow cleanly.<br>
<br>
(This rabbit hole goes deeper; in theory there could be local
methods wherever a statement goes, such as:<br>
<br>
   int x = switch (z) { <br>
       case 0 -> {<br>
           int f(z) { ... }<br>
           yield f(z);<br>
       }<br>
   }<br>
<br>
... and one of these fellows could go in a static initializer. <br>
<br>
Again, we get to decide how deep down the rabbit hole we want to
go.)<br>
<br>
<blockquote type="cite"
cite="mid:CAC1Wh8ErVgE3JpJGCrwmg=XO77pz0iRfap2PgivCN--NS91omA@mail.gmail.com"><br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, Jan 7, 2020 at 12:31
PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com"
moz-do-not-send="true">brian.goetz@oracle.com</a>> wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> <font size="+1"><tt>Everything about nesting in Java is
a mess. The terminology is a mess (top level classes,
nested classes, inner classes, local classes, anonymous
classes); the set of restrictions on what can nest in
what is ad-hoc (can have local classes but not local
interfaces; inner classes cannot have static members,
including static nested classes), and the set of rules
about what must be, can be, or cannot be static is also
ad-hoc (nested classes can be static or not, nested
interfaces are implicitly static, but local and
anonymous classes may not be static, even though it
might make sense.)Â On top of that, we can nest classes
in methods (sometimes) and methods in classes but not
methods in methods (local methods). <br>
<br>
Not only does this make for a lot of accidental
complexity in specification, implementation, and user's
brains, but it means every feature interact with this
complexity. Nested records are implicitly static, but
this meant that in 14 we can't have nested records in
non-static classes, because, non-static classes can't
have static members. (Yes, this could be fixed; hold
your "why don't you just" suggestions.)Â And we borked
up the implementation of local records the first time
around, where they accidentally capture effectively
final locals, which they shouldn't -- because we'd never
really charted the "static local class" territory, and
got it wrong the first time. (Yes, this can be fixed
too, and will be before 14 goes out.)Â <br>
<br>
So, I'd like to propose a simpler, general story of
nesting (which is consistent with the ad-hoc rubbish we
have) which we can get to in stages. The purpose of
this mail is to discuss the model; in what increments we
get there is a separate story.<br>
<br>
Goals:<br>
 - Anything (class, interface, record, enum, method) can
be nested in anything;<br>
 - Some things are always static (enums, records,
interfaces) when nested; the rest can be made static
when desired;<br>
 - The rule about "no static members in nonstatic nested
classes" has to go;<br>
 - Rules about whether members / locals from enclosing
contexts can be specified in a single place, using local
reasoning.<br>
<br>
The core of this is coming to an understanding of what
"static" means. When construct X nests in Y (whether X
and Y are classes, methods, interfaces, etc), for "X" to
be "static" means that nesting is being used purely for
purposes of namespacing, and not for purposes of having
access to names (locals or nonstatic class members) from
enclosing constructs. <br>
<br>
Unfortunately all the terms we might use for whether or
not a symbol in an outer construct can be used in a
nested construct -- such as "accessible" -- are
overloaded with other meanings. For purposes of this
discussion, let's call this "capturable" (this is also
overloaded, but less so.)Â Each construct (class type or
method) has two sets of names from outer constructs that
are capturable -- a _statically capturable_ set SC(X),
and a _non-statically capturable_ set NC(X). We can
define capturability using local reasoning:<br>
<br>
Base cases:<br>
 - Names of static members in X are in SC(X);<br>
 - Names of instance members of X (if X is a class) or
effectively final locals of X (if X is a method) are in
NC(X); <br>
<br>
Induction cases, where X is nested directly in Y:<br>
 - SC(Y) is in SC(X)<br>
 - If _X is not static_, then NC(Y) is in NC(X)<br>
<br>
We then say that X can capture names in SC(X) and NC(X);
all we need to compute capturability is the capture sets
of X's immediately enclosing construct, and whether X is
static or not in that construct (modulo shadowing etc.)Â
<br>
<br>
For the math-challenged, what this means is:<br>
 - A nested construct can access static members of all
the enclosing constructs;<br>
 - A nested non-static construct can access instance
members and effectively final locals of all enclosing
constructs, up until we hit a static construct, and then
capturing stops. (So if Z is nested in Y is nested in
static X, Z can access instance members / eff final
locals of Y and X but not anything non-static from
outside of X.)Â <br>
</tt></font><br>
<font size="+1"><tt><font size="+1"><tt>Note that this is
consistent with what currently happens when X is a
method as well as a class type; static methods in a
class "capture" the static members of the enclosing
class, and instance methods also capture the
instance members of the enclosing class -- and also
consistent with capturing in lambdas and anonymous
classes, if we assume that these are always
non-static constructs.<br>
<br>
</tt></font>We then say enums, records, and interfaces
are _always_ static when nested, whether declared so or
not, we eliminate the restriction about static members
in non-static nested classes (now that we have a clear
semantics for them), and allow local classes to be
declared as static. (Eventually, we also relax the
restrictions about methods in methods, static or not.)Â
<br>
<br>
(Additionally, the model supports the notion of "static
lambda" and "static anonymous class" with obvious
semantics (can't capture anything); we can decide later
whether adding this flexibility is worth the additional
surface syntax.)<br>
<br>
This is a strict superset of the status quo, and yields
a more flexible and regular language -- and hopefully a
simpler spec (since so many of these cases are specified
as ad-hoc corner cases.)Â <br>
<br>
<br>
</tt></font> </div>
</blockquote>
</div>
</blockquote>
<br>
</body>
</html>