Loosening requirements for super() invocation

Brian Goetz brian.goetz at oracle.com
Tue Jan 24 23:16:45 UTC 2023


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/20230124/4ed769d3/attachment.htm>


More information about the amber-dev mailing list