<div dir="ltr"><div dir="ltr">On Tue, Nov 1, 2022 at 11:45 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" target="_blank">brian.goetz@oracle.com</a>> wrote:<br></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">

  
  <div>
    So, what you're saying is that we can't immediately promote these to
    errors, but that doesn't mean we can't have warnings.  (We are
    fairly disciplined about zero-warnings in the JDK, using
    @SuppressWarnings to augment type checking with human judgment.)  <br>
    <br>
    Warnings are an important part of the safety story.  For example,
    generics are subject to heap pollution because of erasure, but we
    make a strong guarantee anyway: if the entire codebase compiles
    without raw or unchecked warnings, then the synthetic casts
    introduced by the compiler at the boundary of generic and
    non-generic code are guaranteed to succeed.  Similarly, while it is
    a high bar, if we can reliably warn about this-escape, we can make a
    similar guarantee for the final-field initialization safety
    guarantees, which are voided by this-escape.</div></blockquote><div><br></div><div>Yes, I really like this idea... so you could compile with something like <span style="font-family:monospace">javac -Xlint:thisEscape</span> and get all the 'this' escapes reported as warnings. Developers could control it using the usual methods, i.e., command line flags and/or <a class="gmail_plusreply" id="m_-4809810071254713399m_-7284996970446163686plusReplyChip-2"><span style="font-family:monospace">@SuppressWarnings</span> annotations.</a><br></div><div><br></div><div>Of course the devil is in the details...  <br></div><br><div>First of all, when should this rule apply?</div><div><br></div><div>At any point in a constructor (one that successfully compiles), the new object is always definitively in one of three states:<br></div><div><div><br></div><div>State 0: neither <span style="font-family:monospace">super()</span> nor <span style="font-family:monospace">this()</span> has been invoked; neither the superclass nor this class are initialized</div><div>State 1: <span style="font-family:monospace">super()</span> has been invoked, so the superclass is initialized, but at least one final field in this class has not been initialized<br></div><div>State 2: <span style="font-family:monospace">super()</span> has been invoked and all final fields in this class have been initialized</div><div><br></div><div>BTW, the current state is easily tracked within the existing DA/DU analysis of the prototype patch.<br></div><div><br></div><div>The possible state transitions are:</div><div><br></div><div>- <span style="font-family:monospace">super()</span> takes you from:</div><div>  - State 0 → State 1 if there remain any uninitialized final fields</div><div>  - State 0 → State 2 if there are no remaining uninitialized final fields</div><div>- <span style="font-family:monospace">this()</span> takes you from State 0 → State 2</div><div>- Initializing the last final field takes you from:</div><div><div>  - State 0 → State 0<br></div><div>  - State 1 → State 2</div><div><br></div><div>Presumably the 'this' escape analysis should only apply in State 1. This is when the object is vulnerable because it's half initialized.</div><div><br></div><div>One might also argue that "uninitialized final fields" should be replaced by "fields that are yet to be assigned later in the constructor" or somesuch. After all, just because a field isn't final, that doesn't mean it's not requiring initialization. Or maybe there should be some other way to denote such fields, e.g., a new <a class="gmail_plusreply" id="plusReplyChip-4"><span style="font-family:monospace">@RequiresInit</span> annotation.</a><br></div><div><br></div></div></div><div><div>Assuming you're in State 1, what exactly would constitute a detectable 'this' escape?</div><div><br></div><div>Could be something like this:<br></div><div><br></div></div><div><div>- Invoking any non-static method on an object known to be equal to 'this'.<br></div><div>- Passing an object known to be equal to 'this' as a parameter to any method or constructor (including implicit outer instance and free variable proxy constructor parameters).</div><div>- Throwing 'this'<br></div><div><br></div><div>In other words, the 'this' instance literally cannot escape the constructor's stack frame.<br></div><div><br></div></div><div>For the meaning of "known to be equal to 'this'", we would be limited in our ability to infer it in the usual ways (Turing complete, blah blah), so you'd still be able to evade the warning e.g.:<br></div><div><br></div><div><span style="font-family:monospace">    public class MyClass implements Iterator<Object> {</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">        private final int <span style="font-family:monospace">limit</span>;</span></div><div><span style="font-family:monospace">        private int count;<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">        public MyClass(int <span style="font-family:monospace">limit</span>) throws IOException {</span></div><div><span style="font-family:monospace">            ((<span style="font-family:monospace">Iterator<?></span>)(Object)this).hasNext();   // always returns false!<br></span></div><div><span style="font-family:monospace">            this.<span style="font-family:monospace">limit</span> = limit;<br></span></div><div><span style="font-family:monospace">        }</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">        <a class="gmail_plusreply" id="plusReplyChip-3">@Override</a></span></div><div><span style="font-family:monospace"><a class="gmail_plusreply" id="plusReplyChip-3">        public boolean hasNext() {</a></span></div><div><span style="font-family:monospace"><a class="gmail_plusreply" id="plusReplyChip-3">            return this.count < this.limit;<br></a></span></div><div><span style="font-family:monospace"><a class="gmail_plusreply" id="plusReplyChip-3">        }<br></a></span></div><div><span style="font-family:monospace">    }<br></span></div><br><div>So it doesn't seem like an ironclad guarantee like "no 'this' escape warnings implies no uninitialized final variables" analogous to the "no unchecked warnings implies no ClassCastExceptions" is possible. But still, knowing your constructor generates zero warnings would be really useful.<br></div><div><br></div><div>So what do you think would be reasonable definitions for "detectable 'this' escape" and "known to be equal to 'this'" ?</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><br>
    <blockquote type="cite">
      <div dir="ltr">
        <div>So this change does not make the problem of "this" escape
          any worse than it already is. That means the two problems are
          really separate and can be addressed separately and
          independently.</div>
      </div>
    </blockquote>
    <br>
    I get where you're coming from; you have a patch that you'd like to
    see integrated, so you're trying to keep the requirements narrow. 
    But realistically, this patch surely needs a JEP, because it affects
    the language spec and the user-visible programming model.  And such
    a JEP is going to be more compelling if it addresses the
    closely-related issue of this-escape.<br>
  </div>

</blockquote></div><br clear="all"><div>That sounds fine to me as long as we can satisfy ourselves with the requisite details.<br></div><div><br></div><div>-Archie<br></div><div><br></div>-- <br><div dir="ltr">Archie L. Cobbs<br></div></div>