<div dir="ltr"><div><div dir="ltr">On Wed, Jan 25, 2023 at 8:05 PM John Rose <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>> wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>


<div><div style="font-family:sans-serif">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.?  </div></div></blockquote><div><br></div><div>That's a question I'd like to better understand as well.</div><div><br></div><div>Brian pointed out the commonality between code and spec - both are going to require some refactoring when a change is made... i.e., we can't just add a footnote that says, "Oh and one more thing: everything we just said is true except that code prior to super() ..."</div><div><br></div><div>So the question is mostly about how much refactoring will be required, as the refactoring is likely to be most of the "diff weight".</div><div><br></div><div>It's still an open question in my mind but also I need to do more study. Brian has a definite opinion here and he's probably right but I want to confirm that for myself...<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:sans-serif">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 (<i>mutable</i> 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:
<div style="white-space:normal"><ul>
<li>
<p dir="auto">Before super-init, any <i>local</i> field, <i>without an initializer</i> (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></ul></div></div></div></blockquote><div>So if I understand what you're getting at, you're saying "Prior to super(), if you assign a value to a non-final field, we're going to treat it as if the field were actually final".</div><div><br></div><div>But I don't understand what that buys us compared to just leaving the rules for non-final fields alone (I'm sure I'm missing something).<br></div><div><br></div><div>So what if you can assign them more than once? No harm there. And developers may scratch their heads if this code:</div><div><br></div><div style="margin-left:40px"><span style="font-family:monospace">public class Foo {<br></span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    private int ival;<br></span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    public Foo(float fval) {</span></div><div style="margin-left:40px"><span style="font-family:monospace">        this.ival = (int)fval;</span></div><div style="margin-left:40px"><span style="font-family:monospace">        if (!Float.isFinite(fval))</span></div><div style="margin-left:40px"><span style="font-family:monospace">            this.ival = -1;</span></div><div style="margin-left:40px"><span style="font-family:monospace">        super();<br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    }</span></div><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div><div><br></div><div>generates an error like this:</div><div><br></div><div style="margin-left:40px"><span style="font-family:monospace">Foo.java:8 error: variable ival may have already been assigned<br>            this.ival = -1;<br>                ^</span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:sans-serif"><div style="white-space:normal"><ul><li>Before super-init, the names <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)">this.f</code> and <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)">f</code>, where <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)">f</code> means <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)">this.f</code>, are treated identically, and there is no other expression which can be used to assign to <code style="margin:0px;padding:0px 0.4em;border-radius:3px;background-color:rgb(247,247,247)">f</code>.  (This is true for finals after super-init as well.)</li></ul></div></div></div></blockquote><div>Yes, something limited like this would be needed. We already have the same limitation when assigning final fields - as you describe in <a href="https://bugs.openjdk.org/browse/JDK-8193904" target="_blank">JDK-8193904</a>.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:sans-serif"><div style="white-space:normal">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%.

</div></div></div>


</blockquote></div><br clear="all"></div><div>I totally agree... you said it much better than me.</div><div><br></div><div>-Archie</div><div><br></div><div>-- <br><div dir="ltr">Archie L. Cobbs<br></div></div></div>