<!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>