<div dir="ltr"><div>Hi folks,</div><div><br></div><div>Hello, I'm new here.</div><div><br></div><div>As a result of trying to be less of a complainer and more of a problem solver in life, I've decided to try to contribute fixes to some javac bugs that have particularly annoyed me over the years.</div><div><br></div><div>Unfortunately I already screwed up and submitted my first PR before discovering <a href="http://openjdk.java.net/guide/">The
OpenJDK Developer's Guide</a> - my apologies. A very handy reference!</div><div><br></div><div>Now I'm enlightened, and so first I need to backfill and...<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>2. Socialize your change<br><br>Once the OCA is signed, please restrain your urge to create a PR just a little while longer. In order to prepare the community for your patch, please socialize your idea on the relevant mailing lists. </div></blockquote><div><br></div><div><div><div>OK let's talk about this bug and this fix. The bug <a href="https://bugs.openjdk.org/browse/JDK-8043179">JDK-8043179</a> is really due to a more general problem with the JLS, which is described in <a href="https://bugs.openjdk.org/browse/JDK-8043176">JDK-8043176</a>:</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>Chapter 16 is missing rules for handling DA/DU analysis of lambda expressions... To detect assignments to blank final fields, a field is *never* DU 
before the lambda body.  (The intuition is that the timing of the body 
invocation is unknown, so we don't know whether the variable has been 
initialized or not.)
</div></blockquote><div><br></div><div>That spec bug was fixed a long time ago; now <a href="https://docs.oracle.com/javase/specs/jls/se19/html/jls-16.html#jls-16.1.10">the spec says</a>:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p class="gmail-norm-static">If an expression is a lambda expression, then the following rules apply:
               </p>
               <div class="gmail-norm">
                  <ul class="gmail-norm" style="list-style-type:disc"><li class="gmail-listitem">
                        <p class="gmail-norm-static"><a name="jls-16.1.10-110-A"></a>
                                 <span class="gmail-type">V</span> is [un]assigned after the expression iff <span class="gmail-type">V</span> is [un]assigned
                                 before the expression.
                        </p>
                     </li><li class="gmail-listitem">
                        <p class="gmail-norm-static"><a name="jls-16.1.10-110-B"></a>
                                 <span class="gmail-type">V</span> is definitely assigned before the expression or block that
                                 is the lambda body (<a class="gmail-xref" href="https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.27.2" title="15.27.2. Lambda Body">§15.27.2</a>) iff <span class="gmail-type">V</span> is
                                 definitely assigned before the lambda expression.
                        </p>
                        <p class="gmail-note">
                                 No rule allows <span class="gmail-type">V</span> to be definitely unassigned before a lambda
                                 body. This is by design: a variable that was definitely
                                 unassigned before the lambda body may end up being assigned to
                                 later on, so we cannot conclude that the variable will be
                                 unassigned when the body is executed.
                        </p>
                     </li></ul>
               </div></div></blockquote><div><div>I'm not a JLS expert, so I'd appreciate confirmation, but what I think this is in effect saying is that the DA/DU rules for what you can do with instance fields in a lambda are the same as if that lambda were replaced with the equivalent anonymous inner class - which would make perfect sense! Here's an example of the existing discrepancy:<br></div></div><div> <pre class="gmail-lang-java gmail-s-code-block"><code class="gmail-hljs gmail-language-java">    <span class="gmail-hljs-keyword">import</span> java.util.function.*;
    <span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">class</span> WhyAreTheseDifferent {
        <span class="gmail-hljs-keyword">final</span> Object obj;
    
        <span class="gmail-hljs-keyword">final</span> Supplier<Object> supplier1 = <span class="gmail-hljs-keyword">new</span> <span class="gmail-hljs-title gmail-class_">Supplier</span><Object>() {
            <span class="gmail-hljs-meta">@Override</span>
            <span class="gmail-hljs-keyword">public</span> Object <span class="gmail-hljs-title gmail-function_">get</span><span class="gmail-hljs-params">()</span> {
                <span class="gmail-hljs-keyword">return</span> <code class="gmail-hljs gmail-language-java">WhyAreTheseDifferent</code>.<span class="gmail-hljs-built_in">this</span>.obj;  // no error here
            }
        };
    
        <span class="gmail-hljs-keyword">final</span> Supplier<Object> supplier2 =<br>                       () -> { <span class="gmail-hljs-keyword">return</span> <span class="gmail-hljs-built_in">this</span>.obj; };     // error here
    
        <code class="gmail-hljs gmail-language-java">WhyAreTheseDifferent</code>(Object obj) {
            <span class="gmail-hljs-built_in">this</span>.obj = obj;
        }
    }</code></pre></div><div>If the above interpretation is correct, then the good news is that this is an easy <a href="https://github.com/openjdk/jdk/pull/10381/files#diff-8973dfc1d0ee2ff1319d8753daec3f0be7e9bd0a63e9512c38a0eeed68e5bcaa">three line fix</a>, which is to ignore instance fields when performing DA/DU analysis, in exactly the same way we do when visiting any normal non-initial-constructor method during flow analysis (see <a href="https://github.com/openjdk/jdk/blob/3675f4c2afd10b5042948fc79e62caee5f3874ce/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java#L2287-L2291">this code in <span style="font-family:monospace">Flow.java</span></a>).</div><div><br></div><div>Thanks for any comments/feedback.</div><div><br></div><div>-Archie</div><div><br></div><div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">Archie L. Cobbs<br></div></div></div></div></div>