<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <br>
    <br>
    <blockquote type="cite"
cite="mid:CAGKkBkufNTUbTTfdN=DLbyJiTMPYBXC-kh7Bb5DA4KfSF1PsHw@mail.gmail.com">
      <div dir="ltr">
        <div>It is true that there exist value types which have a
          "zero", which I would define as some *natural* choice of
          default value that will be *blindingly obvious* to any
          consumer. Of course, Point/Complex are the same two examples
          that had leapt to my mind. These are the best case, the only
          value types that will <i>really</i> (almost) join the same
          category as `int` and `double`.*<br>
        </div>
      </div>
    </blockquote>
    <br>
    I think the truth is somewhere in the middle.  Consider the common
    use cases for values.  Most common would be: <br>
    <br>
     - Numerics <br>
     - Tuples / product types<br>
     - Mediating wrappers (e.g., Optional)<br>
     - Structured domain entities -- timestamps, distances, etc<br>
    <br>
    Of these categories, the first two fall into the zeroable bucket;
    the latter two are in the "usually not" bucket, but even then
    sometimes the zero may well be a reasonable default (e.g.,
    Optional).  So let's just say that both categories are populated,
    and neither should be ignored as negligible.  <br>
    <br>
    To be clear, there _are_ going to be costs for types that declare
    themselves nullable.  They'll get the benefit of "flat and dense",
    but will lose out on some other benefits, such as scalarization. 
    Overall I think this is a fair tradeoff; users can opt into this
    treatment, which signals a willingness to pay the costs.  (One of
    the reasons we haven't addressed this issue until now, is that we
    were less confident in our ability to estimate the costs.)<br>
    <br>
    <blockquote type="cite"
cite="mid:CAGKkBkufNTUbTTfdN=DLbyJiTMPYBXC-kh7Bb5DA4KfSF1PsHw@mail.gmail.com">
      <div dir="ltr">Unfortunately I suspect these are very rare in
        practice. Most code is business logic</div>
    </blockquote>
    <br>
    Well, most of your code, anyway.  The scientific programming / ML
    folks might have a different opinion!  <br>
    <br>
    <blockquote type="cite"
cite="mid:CAGKkBkufNTUbTTfdN=DLbyJiTMPYBXC-kh7Bb5DA4KfSF1PsHw@mail.gmail.com">
      <div dir="ltr">These zero-less types we could divide into two
        groups: those that at least have some combination of field
        values that is <i>invalid</i>, and those that don't, and are
        unwilling to add a field now in order to achieve that. The
        latter have no possible way to be nullable, and the former have
        a possible way to be nullable that is just plain <i>weird</i> (user
        provides a sample value that is not allowed to actually exist,
        so that that can be used as the internal representation of what
        is surfaced in the language as null.). As weird as that is, at
        least it would provide actual nullability instead of awkward
        attempts to simulate what nullability already is, so I think it
        actually does a better job of confining the weirdness?</div>
    </blockquote>
    <br>
    Agree that leaning on the existing behavior of nullability is the
    winning move here, rather than creating a new notion of null-like
    for values ('vull', NullValueException, etc.)  <br>
    <br>
    The game here is to give the user enough control to say "this is
    what a null is", without punishing all other users for that
    flexibility.  (Its tempting to say "just use the no-arg constructor
    to dispense an unused bit pattern", as C# does, but this has serious
    costs throughout the rest of the system, including on value types
    that don't take advantage of this.)  So we're focusing on how we can
    optimize _detection_ of uninitialized values.  So, some interesting
    buckets: <br>
    <br>
     - Types like `int`, where all bit patterns are valid.  These guys
    have a stark choice; add an extra boolean (which could come with a
    severe density price tag), or forego uninitialized-value detection. 
    <br>
     - Types that have naturally unused bits, like LocalDateTime (96
    bits) or better, FourteenBitShort.  The normal alignment
    requirements will hand us these unused bits.  <br>
     - Types that have fields that are never zero/null in an properly
    initialized class.  I suspect this is a common case, and this could
    be used to considerably reduce the cost of the "are you
    uninitialized" check.  <br>
    <br>
    In the first case, even checking all the bits for zero isn't enough;
    you have to inject a new field.  But then you are reduced to the
    case that is shared with the other buckets -- that there's always a
    no-bigger-than-a-word bitfield whose zeroes can be used as a proxy
    for uninitialized.  This is starting to look attractive, as we can
    bring the cost of a null-check down to a single-word mask-and-test. 
    <br>
    <br>
    There's a certain degree of VM gymnastics we would need to do to
    move the costs to where they don't punish everyone else.  The
    functional requirements would be: <br>
     - field access / method invocation when receiver is an
    uninitialized instance of "nullable" values throws an NPE;<br>
     - "boxing" a "null" Foo.val to Foo.box yields true null;<br>
     - "unboxing" a null Foo.box yields a "null" Foo.val (rather than
    NPE)<br>
    <br>
    I can think of at least three or four ways to get there, with
    different cost models.  <br>
    <br>
    <br>
  </body>
</html>