Loosening requirements for super() invocation

Brian Goetz brian.goetz at oracle.com
Wed Jan 25 18:49:25 UTC 2023


Thinking more on this -- I think there is significant simplicity 
dividend here if we relax our goals a little bit.  Supporting constructs 
such as

         if (bar)
             this(f(bar));
         else
             this(g(bar), 0);

would require a full DA/DU analysis, but if the goal is really "allow 
statements before the this/super", we can get by with a considerably 
simpler feature.

On the latter path, we define a grammar production for "constructor 
body" that amounts to:

     statement*
     [super | this]?
     statement*

We further constrain the statement grammar / description to exclude 
`this(...)` or `super(...)` calls, since the only place they can appear 
is in a constructor, and now there's a place for them to explicitly live.

We can use similar language to say "if there isn't a super/this, you get 
one for free at the top" as we do today.

We can use similar "introduces a static context" approach for the 
statements prior to the super/this, and the super/this, as we do today.  
This is enough to prevent use of `this`, explicitly or implicitly, in 
the statements preceding the explicit super/this, including in lambdas, 
try blocks, etc.

I don't think there's any need to update DA/DU.

This brings the spec footprint down considerably, while still 
eliminating complex/risky workarounds around "super first".

On 1/24/2023 6:16 PM, Brian Goetz wrote:
> Hit "send" a little too soon.
>
> The assertion that governs "no use of `this` in a super/this call" is 
> in 8.8.7.1:
>
>> An explicit constructor invocation statement introduces a static 
>> context (§8.1.3),
>> which limits the use of constructs that refer to the current object. 
>> Notably, the
>> keywords this and super are prohibited in a static context (§15.8.3, 
>> §15.11.2),
>> as are unqualified references to instance variables, instance 
>> methods, and type
>> parameters of lexically enclosing declarations (§6.5.5.1, §6.5.6.1, 
>> §15.12.3).
>
> This needs to be generalized to speak about the use of `this` 
> throughout the constructor body; basically, that you can never use 
> `this` (explicitly or implicitly) prior to to the super/this call.
>
> There are a few ways you could do this:
>
>  - A full-blown treatment of DA/DU for `this`;
>  - An extension of the "introduces a static context" used in this 
> section, that covers the entire initial segment of the constructor 
> body up through and including the this/super-call.
>
> Similarly, you'll need a way to restate the "if it doesn't start with 
> `this/super`, you get an implicit super" to the more flexible notion 
> being outlined here.  This is tricky because the obvious way to do 
> this is to run DA/DU on the explicit body of the constructor and ask 
> if `this` is DA at all points where the constructor could complete 
> normally, and if not, prepend a super() call and rerun DA/DU.  This 
> moves us from a strictly syntactic rule to one that appeals to a 
> complex analysis.
>
> We can simplify this analysis a lot by lowering the target, from one 
> that is based on DA to funneling through a single super/this choke 
> point, where a ctor body with an explicit super/this looks like:
>
>     statement*
>     super/this call
>     statement*
>
> This would rule out constructs like:
>
>     Foo() {
>         if (bar)
>             this(f(bar));
>         else
>             this(g(bar), 0);
>     }
>
> but is a lot simpler to specify and still offers the "stuff before 
> super" benefit.
>
>
>
>
>
> On 1/24/2023 6:01 PM, Brian Goetz wrote:
>> The basic design seems sound enough.  Probably time to dig to the 
>> next level, which is assessing the spec impact.
>>
>> The places to start are Ch16 (definite assignment) and 8.8.7 
>> (constructor bodies).
>>
>> On 1/24/2023 4:24 PM, Archie Cobbs wrote:
>>> On Tue, Jan 24, 2023 at 2:21 PM Brian Goetz <brian.goetz at oracle.com> 
>>> wrote:
>>>
>>>
>>>>     This made me realize there is another missing requirement:
>>>>
>>>>       * Upon normal return from a constructor, the `this` reference
>>>>         must be DA
>>>>
>>>
>>>     So, I think this is true by definition; on normal return from a
>>>     super/this/implicit super call, then `this` *is* DA.
>>>
>>>     You can simplify the rule about try blocks to:
>>>
>>>      - if `this` is DU on entry to a try block, it must be DU on
>>>     normal completion of the try block.
>>>
>>>     Can you simplify further, while still preventing `this` calls
>>>     inside a try block?  I don't think so, since we might want to
>>>     allow a try block before the super/this call.
>>>
>>>
>>> Ok thanks. I admit I'm getting a little out of my league here.
>>>
>>> Does this sound correct?
>>>
>>>  The JLS will be modified as follows:
>>>
>>>  * Remove the requirement that `super()` or `this()` appear as the 
>>> first statement in a constructor
>>>  * Add superclass initialization to the existing constructor 
>>> dataflow analysis as follows:
>>>      * The `this` reference is considered DU on entry to the constructor
>>>      * Before a `this()` or `super()` call, the `this` reference 
>>> must be DU
>>>      * After a `this()` or `super()` call, the `this` reference is 
>>> considered DA
>>>      * Before normal completion of the constructor, the `this` 
>>> reference must be DA
>>>      * If `this` is DU on entry to a `try` block, it must be DU on 
>>> normal completion of the `try` block
>>>      * If no explicit `this()` or `super()` appears in a 
>>> constructor, it is treated as if the first line of the constructor 
>>> were `super()`
>>>  * Add the following restrictions on constructors:
>>>      * No access to `this`, other than assignments to fields, may 
>>> occur unless `this` is DA
>>>      * `super()` and `this()` may not appear within any `try { }` block
>>>  * Clarify that non-static field initializers and initialization 
>>> blocks are executed immediately after `super()` invocation, wherever 
>>> it occurs (see "Initialization Order" below)
>>>
>>>
>>> Thanks,
>>>  -Archie
>>>
>>> -- 
>>> Archie L. Cobbs
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230125/0eea4af0/attachment.htm>


More information about the amber-dev mailing list