<p dir="ltr">This makes sense, I didn't even think about primitives. Although, I might not fully understand what is meant by "somehow observed"? Is it refers to bypassing VM-provided access to a value such as reading memory using Arenas and other low-level APIs? And if yes, how is it possible to even restrict this access?</p>
<p dir="ltr">And also, it's a discovery that even if object value is null, it's primitive fields are still initialized. Is it really how this works? If not, they I guess I just missed the point here, because how can you "observe" unexciting object?</p>
<br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jun 18, 2024, 00:05 Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><u></u>

  
  <div>
    What you are describing is a possible, though less desirable, way to
    implement nullity control, one which could be described as "erased
    nullity".  That is, the language does its type checking (as it does
    with generics) and then throws out the nullity information (as it
    does with generics), potentially inserting checks where it wouldn't
    be able to trust the contents of the variable (as it does with
    generics).  But in the face of interference or separate compilation
    anomalies, these checks can fail.  It would obviously be better if
    we could achieve "bang means provably never null, ever", and that is
    what I was describing through the flow analysis I was alluding to. 
    (Again, all of this will be the subject of more extended writeups,
    in due time.)<br>
    <br>
    A good way to think about why this is important is not with null
    references, but with the physical zero of a value type.  There are
    going to be some value types for which the all-zero representation
    is not only not a good default, but not even a member of the value
    set of the class, such as:<br>
    <br>
        value class IsTrue { <br>
            private boolean isTrue;<br>
            private boolean isFalse;<br>
    <br>
            IsTrue(boolean b) { <br>
                isTrue = b;<br>
                isFalse = !b;<br>
            }<br>
    <br>
            boolean isSane() { <br>
                return isTrue || isFalse;<br>
            }<br>
        }<br>
    <br>
    If we reviewed this class, we would reasonably conclude that
    `isSane` is always true.  However, if we can somehow observe an
    `IsTrue!` before it is written, both booleans would be seen to be
    false, and the sanity check would not hold.  In the case of a null
    reference, dereferencing and maybe getting an NPE is "not so unsafe"
    because we stop before we use the invalid (null) value, but in the
    case of an uninitialized `IsTrue!`, something far worse has happened
    -- a value has escaped that was never created by a constructor,
    which we might actually use.  <br>
    <br>
    This is why we are pursuing strengthening DA analysis in the VM, so
    that such instances will provably never be observed.  <br>
    <br>
    <div>On 6/17/2024 4:56 PM, Olexandr Rotan
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <p dir="ltr">Sorry if I am missing out something, but if
        null-restricted type contains null value (as vm initializes it),
        isn't the null value itself is a marker of the fact that value
        hasn't been set yet?</p>
      <p dir="ltr">As I understand, if you assert non-nullity of null
        able type or type of unknown nullability with some sort of
        syntax (like ! in many languages), when in fact the value is
        null, exception should be thrown, so vm already obligated to
        perform null-check on this assignments. Same goes for reflective
        set, which should be treated as unknown nullity in any condition
        I guess unless vm could specialize instructions for the same
        method call but different nullity of args (either way vm must
        check nullity of value in at least part of the situations). This
        leads to a fact that if person even somehow manages to sneak
        through compiler analysis and try to set null to non-nullable
        field, it will immediately fail. Therefore, if value is null -
        it is unset.</p>
      <p dir="ltr">That said, does it in fact matter that VM initializes
        this fields with null, if null bit (I guess that is how it
        stored), in fact is a marker of whether field has been
        initialized or not? VM could just check if value of field is
        null, and if so, throw an exception. Moreover, one way or
        another, as you said, checks on value access must be performed.
        So is this analysis really converges to "check if field is
        null", or there is more to it and I miss it?</p>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Mon, Jun 17, 2024, 22:16
          Chen Liang <<a href="mailto:chen.l.liang@oracle.com" target="_blank" rel="noreferrer">chen.l.liang@oracle.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
          <div dir="ltr">
            <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
              Indeed, another feature about the strict fields is their
              strong encapsulation against reflective setters; another
              safeguard against representable invalid values and their
              friendliness toward constant folding. John Rose's chart
              here seems up-to-date:
              <a href="https://cr.openjdk.org/~jrose/values/objects-reloaded.pdf" id="m_6935075423426606995m_3410378193432181352OWA0d36cf91-2937-4e9b-82ba-9a4603de3f21" rel="noreferrer noreferrer" target="_blank">
                objects-reloaded (openjdk.org)</a> (This strictness can
              also benefit the upcoming Stable Values JEP)</div>
            <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
              <br>
            </div>
            <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
              Also for readers' convenience, I think this is the
              earliest and most comprehensive document about the strict
              field designs, seems still accurate for the most part:
              <a href="https://cr.openjdk.org/~jrose/jls/constructive-classes.html" id="m_6935075423426606995m_3410378193432181352OWA405e510c-1185-9f67-e6fd-7b6105ee1b81" rel="noreferrer noreferrer" target="_blank">
                Cleanup on aisle zero: Constructive classes
                (openjdk.org)</a></div>
            <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
              <br>
            </div>
            <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
              - Chen</div>
            <hr style="display:inline-block;width:98%">
            <div id="m_6935075423426606995m_3410378193432181352divRplyFwdMsg" dir="ltr"><font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b> Brian Goetz <<a href="mailto:brian.goetz@oracle.com" rel="noreferrer noreferrer" target="_blank">brian.goetz@oracle.com</a>><br>
                <b>Sent:</b> Monday, June 17, 2024 1:00 PM<br>
                <b>To:</b> Chen Liang <<a href="mailto:chen.l.liang@oracle.com" rel="noreferrer noreferrer" target="_blank">chen.l.liang@oracle.com</a>>;
                <a href="mailto:valhalla-dev@openjdk.org" rel="noreferrer noreferrer" target="_blank">valhalla-dev@openjdk.org</a>
                <<a href="mailto:valhalla-dev@openjdk.org" rel="noreferrer noreferrer" target="_blank">valhalla-dev@openjdk.org</a>><br>
                <b>Subject:</b> Re: Null restriction on interface typed
                fields</font>
              <div> </div>
            </div>
            <div><font size="4" face="monospace">Yes, the eventual plan
                is that all references can be null-restricted.  We've
                been struggling with a specific problem, though, which
                is that for a reference type like `String!` or
                `Runnable!`, the VM is going to initialize such
                variables with .. null.  This is obviously a safety
                problem, because we've put a value in a variable that is
                not provably within the value set of the variable's
                type.  It was for this reason that earlier discussion
                focused on nullity control for (implicitly
                constructible) values first, and other types later.<br>
                <br>
                Since then, we've figured out that we can solve this
                problem with better flow analysis.  Just like the DA
                analysis done by the compiler, the VM can do a similar
                analysis during verification time of fields that the
                compiler marks as "must be written before they are read"
                (where any this-escape might lead to reading those
                fields.)  This goes under the name of "strict fields",
                and we should be writing more about this soon. 
                <br>
                <br>
                Once we have this tool in our kit, the limitations on
                what types can be null-restricted -- and the safety with
                which we can enforce this -- will be greatly broadened.<br>
              </font><br>
              <div>On 6/9/2024 5:04 AM, Chen Liang wrote:<br>
              </div>
              <blockquote type="cite">
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  Hello valhalla community,</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  In our current iteration of valhalla, we only support
                  null restriction on value fields, as for references,
                  null is a valid default value. Meanwhile, interfaces
                  are not restricted to be value or identity, yet some
                  value classes will only be represented via interfaces,
                  most notably Map.entry().</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  <br>
                </div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  In addition, consider this scenario in the ClassFile
                  API: we have ClassBuilder.withMethod(xxx,
                  Consumer<MethodBuilder>) and
                  withMethodBody(xxx, Consumer<CodeBuilder>). A
                  straightforward implementation of withMethodBody would
                  be withMethod(xxx, new WithCode(cbConsumer)), where
                  WithCode is (value) record
                  WithCode(Consumer<CodeBuilder> build) implements
                  Consumer<MethodBuilder>...</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  In this WithCode record, we can see that we are
                  interested in declaring "build" null-restricted; if
                  build is a value lambda that simply captures context
                  variables, then WithCode can be inlined to the same
                  captures should "build" be NR, without concerns about
                  representing a null build value in the inlined form.</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  <br>
                </div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  Another example is in Algebraic types:</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  sealed interface Operation permits O1, O2, ...</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  Record O1(Interface1 xxx)</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  Record O2(Interface2 xxx)</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  For value-based Interface1 and Interface2 values, we
                  might seek to NR the fields so the record
                  representations can be simpler.</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  <br>
                </div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  Thus, I recommend considering support for NR on
                  interface fields in addition to on explicit value type
                  fields. Though this might lead down to the rabbit hole
                  of "heap pollution of null on reference pointers", I
                  still believe its benefit outweighs its cost,
                  especially in cases where these values can be
                  restricted on the stack in escape analysis, as in most
                  functional APIs (function only invoked conditionally,
                  function objects not stored when method exits).</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  <br>
                </div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  Chen Liang</div>
                <div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
                  <br>
                </div>
              </blockquote>
              <br>
            </div>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </div>

</blockquote></div>