Loosening requirements for super() invocation

Brian Goetz brian.goetz at oracle.com
Wed Jan 25 20:19:30 UTC 2023


> I guess what I meant is that I'm surprised by the notion that this 
> change would present a major problem in terms of updating the spec. 
> The changes we want to make are clear (at least, they seem reasonably 
> clear for this point in the process) so it's just a matter of 
> articulating them precisely and unambiguously. Yes, I'm sure this will 
> be tedious, but it shouldn't be overwhelmingly difficult. Heck if you 
> point me at the JLS source code, I'll be happy to take a novice stab 
> at it.

Nothing is impossible, of course.  But language changes are almost 
always more costly and impactful than initially assumed, especially when 
you've not been doing it for decades.  So guiding towards lower cost / 
lower risk, and asking "is the incremental benefit worth the incremental 
cost", is usually profitable.

The PDFs of the spec are freely available; the sources are not easily 
accessible, since they are not open-sourced.  But you can work with the 
PDF text well enough; "replace the paragraph X with Y" should be good 
enough for an initial iteration.

> To that end, what are the problems with the plan outlined in the 
> previous email?
>
>     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.
>
>
> I'm not completely understanding this. Wouldn't it be simpler to just 
> say that for any constructor in which this()/super() nowhere appears, 
> the analysis starts with `this` being DA instead of DU? Or 
> equivalently, the analysis proceeds as if super() were inserted as the 
> first statement in the constructor.

For example, here's a constructor that contains a `this()` call, but for 
which `this` is not DA at the end:

C() {
     if (foo)
         this(3);
}

As it turns out, there's nothing we can do to save this constructor; 
we're going to error out due to flow issues.  But we have to do a fair 
amount of work before we can figure that out.  But the mere syntactic 
presence or absence of a super/this call is not obviously sufficient.

The current rule about implicit supers is _syntactic_; we need only look 
at the parse tree and ask "was there an explicit super call", and know 
immediately whether we have to treat things as if there were a synthetic 
one, or not, before doing any analysis.  But a DA/DU-based rule means we 
have to speculatively perform linguistic analysis on the code (type 
checking, flow analysis, etc) to even determine whether this is really 
the code we want to work with in the first place, or whether we have to 
mangle it and then do it all again.  (Even this description is more a 
description of what the compiler will do; the spec doesn't talk about 
processing or type checking as a thing that happens, and so leans more 
heavily on things happening in a certain order in order for such 
analysis to be well-defined.)

Additionally, since we currently quarantine the cases where `this` is DU 
to the single explicit constructor call, we don't have to thread DA of 
`this` throughout the rest of the JLS; the generalization would likely 
send tentacles farther and wider (e.g., lambda bodies, switch 
expressions, etc.)



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230125/5793a9c7/attachment-0001.htm>


More information about the amber-dev mailing list