<div dir="ltr"><div dir="ltr">On Tue, Feb 7, 2023 at 4:48 PM Archie Cobbs <<a href="mailto:archie.cobbs@gmail.com">archie.cobbs@gmail.com</a>> wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>FWIW in the JEP I've raised the importance of fixing this <a href="https://bugs.openjdk.org/browse/JDK-8301649" target="_blank">bug in the spec</a> (i.e., that constructor invocation is not really a "static context" but truly something different - what we're calling a "pre-initialization context") and made it one of the "goals" of the JEP, because the gulf between the spec on one hand and the compiler's current behavior (and what everyone has actually been doing for the past decade) on the other hand is pretty glaring.</div></blockquote><div><br></div><div>FYI,</div><div><br></div><div>Along these lines, I've added this new section to the "Motivation" section:</div><div><br></div><div>(Also, presumably people who are interested in following the JEP can 'watch' it, so I won't post any more such updates after this one.)</div><div><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="4">Fixing a Specification Bug

</font><p>JLS §8.1.3 defines <em>static context</em> and notes that "The 
purpose of a static context is to demarcate code that must not refer 
explicitly or implicitly to the current instance of the class whose 
declaration lexically encloses the static context". Going by its stated 
purpose, a static context would seem to naturally apply to code inside a
 <code class="gmail-prettyprint">super()</code> or <code class="gmail-prettyprint">this()</code>
 invocation, and in fact the JLS does just that.  Prior to the advent of
 generics, inner classes, and captured free variables, this yielded the 
correct semantics for superclass construtor invocation.</p>

<p>However, as §8.1.3 notes a static context prohibits:</p>

<ul><li><code class="gmail-prettyprint">this</code> expressions (both unqualified and qualified)</li><li>Unqualified references to instance variables of any lexically enclosing class or interface declaration</li><li>References to type parameters, local variables, formal parameters, 
and exception parameters declared by methods or constructors of any 
lexically enclosing class or interface declaration that is outside the 
immediately enclosing class or interface</li></ul>

<p>Those rules make the following program illegal:</p>

<pre class="gmail-prettyprint" style="margin-left:40px"><code>import java.util.concurrent.atomic.AtomicReference;

public class ClassA<T> extends AtomicReference<T> {

    private int intval;

    public ClassA(T obj) {
        super(obj);
    }

    public class ClassB extends ClassA<T> {
        public ClassB() {
            super((T)null);             // illegal - 'T'
        }
    }

    public class ClassC extends ClassA<Object> {
        ClassC() {
            super(ClassA.this);         // illegal - 'this'
        }
    }

    public class ClassD extends ClassA<Integer> {
        ClassD() {
            super(intval);              // illegal - 'intval'
        }
    }

    public static Object method(int x) {
        class ClassE extends ClassA<Float> {
            ClassE() {
                super((float)x);        // illegal - 'x'
            }
        }
        return new ClassE();
    }
}</code></pre>

<p>But not only has this program compiled successfully since at least 
Java 8, the above idioms are in common use. The mental model that the 
compiler and developers seem to both be using is indeed that code "must 
not refer explicitly or implicitly to the current instance of the class 
whose declaration lexically encloses" the code in question. However, 
this is no longer what a "static context" prohibits; instead, it goes 
beyond that, for example, restricting even references to generic type 
parameters.</p>

<p>The underlying issue is that "static context" is applied to two scenarios which are similar, but not equivalent:</p>

<ol><li>When there is no 'this' instance defined, e.g., within a static method</li><li>When the 'this' instance is defined but must not be referened, e.g., prior to superclass initialization</li></ol>

<p>The current definition of "static context" is appropriate for 
scenario #1, but after the addition of generics, inner classes, and 
captured free variables to the language, no longer for scenario #2. We 
need a new, distinct concept; let's call it a "pre-initialization 
context". The rules for a "pre-initialization context" should align with
 developers' current mental models (and compiler behavior) for what's 
allowed prior to superclass initialization. Once defined, the rules for a
 "pre-initialization context" can then extend to statements prior to 
superclass initialization, and for the same reason.</p></div></blockquote><br></div>-Archie<br clear="all"><div><br>-- <br><div dir="ltr" class="gmail_signature">Archie L. Cobbs<br></div></div></div>