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