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