RFR: 8334248: Invalid error for early construction local class constructor method reference [v3]

Archie Cobbs acobbs at openjdk.org
Mon Jun 17 15:59:23 UTC 2024


On Mon, 17 Jun 2024 11:17:57 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

> And, according to this interpretation, the program in this PR should be rejected.

OK, I want to be slow & careful here because there are a few different things flying around.

First, just to state the obvious, the spec that applies here is the one attached to [JDK-8329079](https://bugs.openjdk.org/browse/JDK-8329079) (CSR for "flexible constructors").

One explicit goal of that spec is to have the compiler treat local and anonymous classes the same way with respect to outer instances. The reason for this is that we want it to be possible to define a usable local class in the constructor prologue. Practically speaking, that means:
* It's legal to define a local class in the constructor prologue.
* It's possible to instantiate that local class in the constructor prologue.

Those two goals imply that the `EarlyLocalCtorRef` given in this PR should successfully compile:

class EarlyLocalCtorRef {

    EarlyLocalCtorRef() {
        class InnerLocal { }
        this(InnerLocal::new);
    }

    EarlyLocalCtorRef(Supplier<Object> s) {
    }
}


Now of course you/we should confirm this with Dan and Gavin, but FWIW that's my understanding of what this new spec is _supposed_ to say and consequently how the compiler is _supposed_ to behave.

So I'd say up front that if the spec doesn't actually say that, then that's a bug in the spec, not the compiler.

In any case, if you are saying the spec does in fact have a rule that disallows the above program, I don't yet see how. There is no static context involved here, so the "static context" clause you cited doesn't apply (instead, it's an early construction context).

More background: To elaborate on "treat local and anonymous classes the same way with respect to outer instances": this means `EarlyLocalCtorRef` should compile, even though class `InnerLocal` would "normally" have an outer instance of type `EarlyLocalCtorRef` (but really doesn't).

Why? It's for the same reason - has the same motivating logic - that this anonymous class example has always compiled, even though the anonymous `Runnable` class would "normally" have an outer instance of type `EarlyAnonRef` (but really doesn't):

class EarlyAnonRef {

    EarlyAnonRef() {
        this(() -> new Runnable() { public void run() { } });
    }

    EarlyAnonRef(Runnable r) {
    }
}

It would be illegal for the anonymous `Runnable` class to refer to `EarlyAnonRef.this`, as it would be for `InnerLocal` to refer to `EarlyLocalCtorRef.this`. But that doesn't (i.e., shouldn't) mean these classes can't be declared and instantiated where they are.

At least, this is my current understanding of what the spec is meant to say and also what the spec actually says. Please confirm with Dan & Gavin though.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/19705#issuecomment-2173780183


More information about the compiler-dev mailing list