<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Thanks Dan,<br>
I see the new rules. So basically, a local class in a
pre-construction context has an enclosing instance, but then we
have a bunch of rules which say that if I do "Type.this", and I'm
in the pre-construction context for Type, that's an error.</p>
<p>I note that this is effectively equivalent to say that the
enclosing instance of the local class is the first enclosing
instance that does not appear in a pre-construction context,
correct? If we stated that, once and for all (in 8.1.3), couldn't
we then avoid the need for having other special rules?</p>
<p>(e.g. if class L appears in a pre-construction context for C, and
C has enclosing instance D, then, if we say that the enclosing
instance of L is D, automatically C.this becomes ill-formed).</p>
<p>Was this possibility considered, or would it be too problematic
to have an enclosing instance not match the innermost lexically
encloisng class?</p>
<p>P.S.</p>
<p>How common is this stuff? This seems to be working today, with
some bits of javac heroics (some bits of which seem to be working
mostly by accident). From the perspective of Java developers,
wouldn't it be easier to say that every class declared in a
pre-construction context is static, period, and cannot reference
anyhing from enclosing contexts? I realize this would be an
incompatible change, but it seems to me that the status quo leaves
developers guessing as to whether some code would compile or not.<br>
</p>
<p>Maurizio<br>
</p>
<div class="moz-cite-prefix">On 30/05/2024 05:39, Dan Smith wrote:<br>
</div>
<blockquote type="cite" cite="mid:D41ADD67-8690-452D-951D-0B02EEEBFE9A@oracle.com">
<div>
<blockquote type="cite">
<div>On May 29, 2024, at 7:57 AM, Maurizio Cimadamore
<a class="moz-txt-link-rfc2396E" href="mailto:maurizio.cimadamore@oracle.com"><maurizio.cimadamore@oracle.com></a> wrote:</div>
<br class="Apple-interchange-newline">
<div>
<div>
<div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
<p style="margin: 0px 0px 1.2em !important;">On
28/05/2024 18:20, Stephan Herrmann wrote:</p>
<div class="markdown-here-exclude">
<blockquote type="cite" cite="mid:89c6e982-5129-47bf-950d-27b5ebe51eb6@berlin.de">
* §8.1.3: "An instance of an anonymous class whose
declaration occurs in a pre-construction context
(8.8.7.1) has no immediately enclosing instance."
</blockquote>
<div><br class="webkit-block-placeholder">
</div>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>To clarify the model: yes, this rule was intentionally
removed. It becomes very complicated if you want to make rules
about which enclosing instances exist or don't exist based on
positioning within a constructor. Example:</div>
<div><br>
</div>
<div>class C1 {</div>
<div> C1() {</div>
<div> super();</div>
<div> class C2 { // not early for C1</div>
<div> C2() {</div>
<div> class C3 { // early for C2</div>
<div> C3() {</div>
<div> super();</div>
<div> class C4 { // not early for C3</div>
<div> ...</div>
<div> }</div>
<div> }</div>
<div> }</div>
<div> super();</div>
<div> }</div>
<div> }</div>
<div> }</div>
<div>}</div>
<div><br>
</div>
<div>Does C4 have a 1st enclosing instance? Yep. 2nd? Maybe no?
3rd? It better...</div>
<div><br>
</div>
<div>Instead, the approach we settled on was: early construction
contexts have no bearing on whether a class "has" an enclosing
instance. It always does, if it's not in a static context.</div>
<div><br>
</div>
<div>Meanwhile, there are a bunch of rules about what you can
reference from an early construction context *of a particular
class*. So, e.g., C4 is in the early construction context of
C2, so it is illegal to reference the members of C2 in the
body of C4.</div>
<div><br>
</div>
<div>(Note that this model has nothing to do with how a compiler
translates these classes into bytecode, which enclosing
instances get stored in fields, etc. That's a separate problem
for javac to deal with.)</div>
<div><br>
</div>
<blockquote type="cite">
<div>
<div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
<div style="margin: 0px 0px 1.2em !important;">Consider
the following example:</div>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code class="hljs language-java" style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); background: rgb(248, 248, 248); -moz-text-size-adjust: none;"><span class="hljs-class"><span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">class</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;color: rgb(68, 85, 136); font-weight: bold;">Outer</span> </span>{
<span class="hljs-class"><span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">class</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;color: rgb(68, 85, 136); font-weight: bold;">Inner</span> </span>{
Inner() {
<span class="hljs-class"><span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">class</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;color: rgb(68, 85, 136); font-weight: bold;">Local</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">void</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">test</span><span class="hljs-params">()</span> </span>{ m(); }
}
<span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">new</span> Local().test();
<span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">super</span>();
}
}
<span class="hljs-function"><span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">void</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">m</span><span class="hljs-params">()</span> </span>{ }
<span class="hljs-function"><span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">public</span> <span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">static</span> <span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">void</span> <span class="hljs-title" style="color: rgb(153, 0, 0); font-weight: bold;">main</span><span class="hljs-params">(String[] args)</span> </span>{
<span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">new</span> Outer().<span class="hljs-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">new</span> Inner();
}
}
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">Here, <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">
Local</code> occurs in an early context (used to be pre-constructor, or
static). So it has no enclosing instance. But then, how
can it refer to
<code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">
Outer::m</code> ?</p>
</div>
</div>
</blockquote>
<div>Revised rules say that Local does not appear in the early
construction context *of Outer*, so therefore is allowed to
refer to the members of Outer.</div>
<br>
<blockquote type="cite">
<div>
<div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
<p style="margin: 0px 0px 1.2em !important;">In 15.12.1 we
say:</p>
<blockquote style="margin: 1.2em 0px;border-left: 4px solid rgb(221, 221, 221); padding: 0px 1em; color: rgb(119, 119, 119); quotes: none;">
<p style="margin: 0px 0px 1.2em !important;">If there is
an enclosing class or interface declaration of which
that method is a member, let E be the innermost such
class or interface declaration. The type to search is
the type of E.this (§15.8.4).
</p>
</blockquote>
<p style="margin: 0px 0px 1.2em !important;">Ok, so the
above program is valid if
<code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">
Outer.this</code> makes sense. But, as per 15.8.4:</p>
<blockquote style="margin: 1.2em 0px;border-left: 4px solid rgb(221, 221, 221); padding: 0px 1em; color: rgb(119, 119, 119); quotes: none;">
<p style="margin: 0px 0px 1.2em !important;">The value
of a qualified this expression TypeName.this is the
n’th lexically enclosing instance of this.
</p>
</blockquote>
<p style="margin: 0px 0px 1.2em !important;">But there’s
no enclosing instance for
<code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">
Local</code>, so what does <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">
Outer.this</code> evaluates to?</p>
</div>
</div>
</blockquote>
<div>Yep, that's part of what motivated this change. You need to
be able to talk about the full chain of enclosing instances of
Local, even if some of them are "unusable".</div>
<br>
<blockquote type="cite">
<div>
<div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
<p style="margin: 0px 0px 1.2em !important;">I think this
has always been a bit of an issue - we always treated
anonymous classes occurring in super calls as “static”,
but that doesn’t explain how such classes seem to have
access to members of enclosing classes.</p>
</div>
</div>
</blockquote>
<div>Agree, it wasn't well-specified before.</div>
<div><br>
</div>
<blockquote type="cite">
<div>
<div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
<p style="margin: 0px 0px 1.2em !important;">It seems like
this area needs a bit of an overhaul? Or am I missing
something?</p>
</div>
</div>
</blockquote>
<div>Right. The first step was to recognize that an early
construction context is not the same thing as a static
context. The next step was to allow enclosing instances for
classes in early construction contexts. And the third step was
to ensure that the restrictions on references from early
construction contexts continue to apply appropriately inside
nested classes.</div>
<div><br>
</div>
<div>I believe this is now appropriately handled by the spec
changes Gavin shared, but it's good to validate that with
extra eyeballs.</div>
<div><br>
</div>
</div>
</blockquote>
</body>
</html>