Draft Spec for Second Preview of Flexible Constructor Bodies (JEP 482)

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Jun 11 14:13:29 UTC 2024


On 11/06/2024 14:05, Stephan Herrmann wrote:
> Am 07.06.24 um 23:23 schrieb Maurizio Cimadamore:
>>
>> On 02/06/2024 22:36, Stephan Herrmann wrote:
>>> Do you consider the proposed rules too complex to implement cleanly, 
>>> or too complex to explain to users? 
>>
>> It's a decent rule and explanation of what the compiler does.
>>
>> The more I play with code like this, the more I find examples where, 
>> on a first look is not immediately clear which way the compiler 
>> should go (it's kind of hard to mentally keep track of which classes 
>> have members that can be accessed), or how they should be translated. 
>> It probably doesn't help that the implementation seems to be all over 
>> the place in this area.
>>
>> So, my argument is mostly a pedagogical one, e.g. drawing a clear 
>> line that is less prone to mis-interpretation and might make the code 
>> slightly more readable and predictable.
>>
>> Maurizio
>
> Here's a different perspective that could also affect the pedagogical 
> aspect:
>
> I've seen academic approaches that tackle the initialization issue by 
> discriminating two variants of every reference type T:
> * type "raw T" captures instances that are not yet fully initialized
> * type "cooked T" is the type of instances with initialization completed
>
> (sorry for overloading 'raw' in this context, I only wish the 
> distinction raw-parameterized could be retired completely :) ).
>
> So, within a constructor 'this' always has a "raw" type, which implies 
> that the things you can do with that value are limited. (In a fully 
> elaborated system this would even allow post-constructor 
> initialization without risk of exposing uninitialized fields, or 
> select which methods can be safely invoked on a "raw" this pointer -- 
> not to mention the great benefit for NPE-analysis).
Yes, and this is more or less how the JVM type system goes about this 
business.
>
> Perhaps some years from now Java will even adopt such type modifiers, 
> but already for the discussion at hand I'd think that the existence of 
> any "Outer.this" can be determined purely based on lexical nesting 
> (unless 'static' is said explicitly), but semantic analysis will know 
> that some of these references will have a "raw type", imposing the 
> necessary restrictions. Maybe existence of enclosing instance 
> references is not boolean but three-valued: absent-raw-cooked.
>
> IOW, I see nothing awkward with enclosing instance references that 
> impose some restrictions on their usage. OTOH the implementation 
> pattern "this.this$0" does *not* require "this" to be fully cooked, 
> right?

I believe you are incorrect here. If you want to access "this.this$0", 
then "this" has to be fully cooked, or you're in for a verifier error.

This is the source of complexity in the implementation (and the cause of 
all the bugs we're seeing): the compiler "thinks" there's some reachable 
enclosing instance via some "this.this$x.this$y..." chain, but that's 
not the case (as that chain contains "missing links").

A more robust approach would be for the local class to capture each and 
every enclosing instance that it uses inside its body, and do not rely 
on a chain of "this.this$x.this$y..." at all.

Another approach would be to still have a chain, but have the chain 
"skip" over the inaccessible enclosing instances.

Maurizio


>
> best,
> Stephan


More information about the amber-spec-experts mailing list