<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">On 25 Jan 2023, at 15:06, Archie Cobbs wrote:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">On Wed, Jan 25, 2023 at 3:57 PM Brian Goetz <brian.goetz@oracle.com> wrote:</p>
<blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">… Doing
<br>
a 40% smaller feature (just going by your "3 out of 5" estimate) at 95%
<br>
lower cost (making up a number here, but the difference appears
<br>
significant) seems worth considering carefully.</p>
</blockquote><p dir="auto">Gotcha. I think I need to spend time getting more familiar with the spec,
<br>
so I can better understand how it's put together, what the trade-offs are,
<br>
etc.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Brian is right; usually these sort of proposals break into layers, and in many cases the first 80% is where we stop.</p>
<p dir="auto">That said, I’d like to put on my DA/DU-expert hat for moment. (I invented the DU part of that analysis for blank finals in 1.1.) This analysis is subtle, understood by nearly nobody. For something that subtle, it delivers amazing value, because javac teaches the users what works and what doesn’t. The result is a very flexible language, and yet the danger areas (uninitialized values) are strongly fenced away from the user.</p>
<p dir="auto">I have always thought that the super() syntax restriction (the “pinch point rule”) is a simple tactic to get the same job done as assigning DA/DU bits to “this”. It’s a blunt instrument compared with the DA/DU analysis, and the spec. for it reads bluntly and simply. You’ll not be surprised that I am intrigued (though not convinced) about the alternative idea of leaning hard on new rules regarding DA/DU for “this”.</p>
<p dir="auto">I’m pretty sure either tactic could be made to work in the JLS. I’m a little more hopeful than Brian that DA/DU bits would do the job well, but sometimes a sledgehammer is better than a samurai sword. What I’m wondering now is, if we use the sledgehammer technique, what is the total “diff weight” of the spec.? Is it just a few touches or many? (It could be many, if various odd corner cases need special treatment, due to the bluntness of the instrument.) Likewise, if we carefully re-slice the DA/DU reasoning to cover “this”, what would the total “diff weight” be?</p>
<p dir="auto">I have an unrelated suggestion (which makes sense with either tactic). The existing DA/DU rules for blank finals are (I think) easy to adapt to allow blank finals initializations to be hoisted above super-init. So far so good. For non-finals (<em>mutable</em> non-static fields), may I suggest that, if you were to allow initializations to them above super-init, that you formulate the restrictions on their treatment to align them with blank finals. Something like this:</p>
<ul>
<li>
<p dir="auto">Before super-init, any <em>local</em> field, <em>without an initializer</em> (whether final or not) is put into the DU state. (Today it is blank finals only.)</p>
</li>
<li>
<p dir="auto">Before super-init, no local fields may be read, and only DU fields may be written. (The JVM is slightly more lenient; we don’t care.)</p>
</li>
<li>
<p dir="auto">Assignments to any field in a DU state put it into the DA state. (After that any further access must occur after super-init.)</p>
</li>
<li>
<p dir="auto">Before super-init, the names <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">this.f</code> and <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">f</code>, where <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">f</code> means <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">this.f</code>, are treated identically, and there is no other expression which can be used to assign to <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">f</code>. (This is true for finals after super-init as well.)</p>
</li>
<li>
<p dir="auto">Immediately after super-init, DA and DU bits are discarded for all non-final variables. This is also the place where field initializers and instance initializers are executed.</p>
</li>
<li>
<p dir="auto">And of course, other than the above (special pleading for local blank fields), no uses of <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">this</code>, either explicit or implicit, are allowed. This may be because the code is textually before the pinch point, or else because “this” is not DA until the super-init call.</p>
</li>
</ul>
<p dir="auto">All this might be in the last 20%, beyond the good 80% we might well adopt. But I did want to put it out there.</p>
<p dir="auto">It is interesting to note that, given the restrictions on local fields in the “early” code, there is almost no way to tell if the field assignments (the permitted early assignments to blank fields) are actually committed to the object, or are just stashed into locals.</p>
<p dir="auto">The only way you can tell if a field is actually committed is for an unusual things to happen. The super-init method has to turn around and access that field, either directly (via a cast), or (more likely) via an instance method with an override in the subclass (which makes a secret cast during virtual dispatch). This is rare but non-unheard-of, and uplevel links of inner classes are sometimes used this way, by super-init calls to virtuals. I think it would be good (if possible) to give this tool to source programmers, and not just to hardwired inner-class links. One more point: This use case could supported in either way: Either eagerly write assigned field values at the assignment point, or stash them in locals, and commit them all just before the super-init call, which is where the possibility of observing the fields begins.</p>
<p dir="auto">This leads me to one more observation: Blank finals can be observed in their uninitialized state during a super-init call. This is a hole in the otherwise strong fence around final variables, and it sometimes causes bad bugs. It will make the fence around finals stronger if we allow them to be initialized before the super-init call. That is, if users take the chance of initializing their blank finals before the super-init call, then there is a very strong proof that no such blank final will ever be observed in its uninitialized state. To me that’s an indication that we should put this feature in the 80% rather than the 20%. The blank non-finals can come along for the ride also, maybe, or maybe they belong in the 20% remainder. If that’s the case, some of my suggestions above (but not all) are still relevant.</p>
</div></div></body>
</html>