<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <blockquote type="cite">In this context, `42` is<br>
      *not* an `int` at all - it is a literal. There is no conversion
      here,</blockquote>
    <br>
    I don't really want to pile on because Ron and Tagir have already
    made it clear that this is simply a misunderstanding of how the
    language works, but there's a deeper point here that makes it useful
    to dig in a little bit further, so I ask some forbearance.  First,
    some necessary chapter and verse: <br>
    <br>
    JLS 3.10 defines literals; integer literals are divided into
    decimal, hex, octal, and binary integer literals.  The spec is quite
    clear that literals like 42 *are*, in fact, integers:<br>
    <br>
    <blockquote type="cite">An integer literal is of type long if it is
      suffixed with an ASCII letter L or l (ell);<br>
      otherwise it is of type int (§4.2.1).</blockquote>
    <br>
    There are no "untyped literals", nor are there literals of type
    byte, short, or char.  (Fun fact: there are also no instructions in
    the JVM for arithmetic on byte, short, or char; these are done with
    `iadd` and friends, and the shorter types are _erased_ to int. 
    Erasure is not just for generics.)  <br>
    <br>
    JLS 5 (which is about conversions) then goes on to define primitive
    widening and narrowing conversions, and state when these conversions
    can be applied.  In an assignment context (JLS 5.2), a special case
    for narrowing constant integral expressions (which includes integer
    literals) to shorter integral types is permitted:<br>
    <br>
    <blockquote type="cite">In addition, if the expression is a constant
      expression (§15.29) of type byte, short,<br>
      char, or int:<br>
      • A narrowing primitive conversion may be used if the variable is
      of type byte,<br>
      short, or char, and the value of the constant expression is
      representable in the<br>
      type of the variable.</blockquote>
    <br>
    This is why `byte b = 0` works; the RHS is a constant expression of
    type `int`, and 0 is known by the compiler to be representable in
    the type `byte`.  (This same language -- a value being representable
    in a given type -- is also the language used in this JEP for when a
    cast is exact.)<br>
    <br>
    So yes, there is a conversion here (JLS 5 is called "conversions and
    contexts").  There is similar language that permits, for example,
    integer case labels to be used in a switch on byte, short, or char
    (or their box types.)  <br>
    <br>
    Now, let's think about what Java would be like without this phrase
    in JLS 5.2; we'd have to cast 0 to byte every time we use a literal
    (or the language would have to have separate syntax for byte
    literals).  That's kind of annoying; this is the spec working for
    you so you don't have to deal with, or even notice, these low-level
    annoyances.  <br>
    <br>
    My point is not to say "see, haha, Stephen doesn't understand Java"
    -- quite the opposite.  Stephen is an accomplished Java programmer,
    who has written excellent Java libraries that we all use every day. 
    My point is that you can be an excellent Java programmer *without
    fully understanding how the language works* -- and that's a feature,
    not a bug!  The essence of Java's "blue collar" success is not that
    the language is so simple that everyone can read and understand the
    spec in an afternoon.  Java is in fact quite complex, but the spec
    is so carefully constructed that most developers can go an entire
    career without opening the spec at all, and much of the complexity
    stays in the shadows.  The spec goes to great lengths so that
    programmers like Stephen can enjoy mental models like "42 is not an
    int, its a literal", and have that not work against them most of the
    time.  It doesn't matter whether these mental models are 100%
    accurate; they are still useful.  <br>
    <br>
    Where mental models become problematic is when they leave your own
    mind and you try to treat them as some sort of law of physics
    (especially when they're wrong.)  Mental models are useful, helpful
    approximations.  "Instanceof means subtyping" is a mental model,
    just like "0 is not an integer, its a literal."  If they help you,
    great, but be very careful about extrapolating past the boundary of
    your own skull.  <br>
    <br>
    The changes in this JEP are in the same spirit as the rules about
    narrowing integer constants; it is about _removing_ anomalies that
    would make construction and deconstruction asymmetric for gratuitous
    reasons, just like the rule about narrowing integer constants to
    byte.  We don't notice it because its working quietly for us.  No
    one clamored for it -- because they never needed to.  If we didn't
    align the meaning of type patterns with existing conversions, as
    people used more complex nested patterns, they'd notice anomalies
    that are analogous to "can't assign 0 to byte".  <br>
    <br>
    I get that this seems like a big change, but really, it's not.  I
    doubt people will all of a sudden start using switches on floats all
    over the place, but it would be weird to be able to switch on every
    type *but* float.  The cure for that is to ensure that switching,
    instanceof, and pattern matching work on every type, whose semantics
    are drawn from a single, common source.  As it turns out, that
    source is in plain view -- casting.  We just have to let it out.  <br>
    <br>
    <br>
    <br>
    <br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 1/27/2023 1:22 AM, Tagir Valeev
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAE+3fjaDFBW3p41za2QBoROFu8yPePiGYpVRbq-BLcsoX3mTAg@mail.gmail.com">
      
      <div dir="auto">
        <div>Hello!<br>
          <br>
          <div class="gmail_quote">
            <div dir="ltr" class="gmail_attr">On Thu, Jan 26, 2023,
              23:01 Stephen Colebourne <<a href="mailto:scolebourne@joda.org" moz-do-not-send="true" class="moz-txt-link-freetext">scolebourne@joda.org</a>>
              wrote:<br>
            </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
              <br>
              In the Motivation section it is claimed that because `byte
              b = 42`<br>
              compiles, it implies that sometimes an `int` can be
              converted to a<br>
              `byte` without a cast. This is nonsense. In this context,
              `42` is<br>
              *not* an `int` at all - it is a literal. There is no
              conversion here,<br>
              `42` is typed as a `byte` because of the assignment. `42`
              is never, at<br>
              any stage, an `int`. At the very least, the JEP should be
              amended to<br>
              remove this part of the Motivation section.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">A small correction: this is not what spec says.
          42 is accepted here not because it's untyped literal but
          because it's a compile time constant expression that fits the
          byte type. Other constant expressions are also accepted here,
          like:</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">byte b = 21 + 21; // obviously not literal</div>
        <div dir="auto">Or even:</div>
        <div dir="auto">final int x = 21;</div>
        <div dir="auto">final int y = 21; // int type is even spelled
          explicitly</div>
        <div dir="auto">byte b = x + y;</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">With best regards,</div>
        <div dir="auto">Tagir Valeev </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">
          <div class="gmail_quote">
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              <br>
              The document proceeds to argue that because switch works
              with Object<br>
              hierarchies:<br>
                Pet p = new Pet(new Dog()); // automatic widening
              conversion from<br>
              Dog to Animal<br>
                switch (p) {<br>
                  case Pet(Dog d)    -> ... d ...<br>
                  case Pet(Animal a) -> ... a ...<br>
                  default            -> ...<br>
                }<br>
              that it must therefore be OK to work with primitives:<br>
                int i = methodReturningShort();<br>
                switch (i) {<br>
                  case byte  b -> ... b ...;<br>
                  case float f -> ... f ...;<br>
                  default      -> -1;<br>
                }<br>
              <br>
              There is simply no comparison here. Dog and Animal are
              subtypes of<br>
              Pet, a concept that has been baked into the language since
              day one,<br>
              and is fully understood by all. By contrast, there is
              absolutely no<br>
              subtyping relationship between int, byte and short, and
              again this<br>
              fact has been baked into the language since day one.<br>
              <br>
              There is a *huge* red line being crossed here. Values in
              Java have two<br>
              distinct parts - the type and the value of the instance.
              Java has<br>
              always kept these two things completely separate:
              General-purpose<br>
              language features operate on types and references/null
              (eg.<br>
              instanceof, catch, switch) or expressions (if, for,
              while). It<br>
              requires an expression or an operator for the actual value
              of the<br>
              instance to be considered. The JEP proposes to shatter
              that boundary,<br>
              saying that the language should now examine not only the
              type but also<br>
              the value of the instance in order to determine flow
              control.<br>
              <br>
              The root cause of the issue here is trying to treat Object
              hierarchy<br>
              conversion and conversion between different primitive
              types as being<br>
              somehow equivalent. They are not. Java does not have a
              mechanism that<br>
              allows a LocalDate to be assigned to a String, even though
              there is a<br>
              perfectly reasonable way to do so. Instead, you have to
              explicitly<br>
              perform the conversion by calling toString(). That is
              because<br>
              `LocalDate` and `String` are separate types with no
              subtype hierarchy.<br>
              Similarly, there is no subtype hierarchy link between
              `int` and<br>
              `long`. That an `int` can be assigned to a `long` is
              merely a<br>
              convenience - it could have required a method call.
              Critically though,<br>
              the convenience conversion is absolute. No runtime check
              of the value<br>
              of the instance is required. This even applies when
              converting `int`<br>
              to `float` which is lossy.<br>
              <br>
              In my view, the only pattern matching checks that make
              sense here are<br>
              those in line with the separation between types and values
              of<br>
              instances. This basic rule implies:<br>
              * `int` vs `Integer` and vice versa - OK, as only requires
              examination<br>
              of the type and reference/null<br>
              * `int` vs `byte` - not OK, as an expression is required
              in order to<br>
              extract the value of the `int` in order to decide flow
              control<br>
              <br>
              In summary, if this was simply about adding a niche
              feature for<br>
              checking whether an `int` actually fits in a `byte` I
              would have no<br>
              problem. For example, were the pattern match to be based
              on an<br>
              expression (ie. a method call) then I would have no
              problem. The key<br>
              issue here is the red line being crossed by having a
              general-purpose<br>
              language feature examine the value of the instance outside
              of an<br>
              expression.<br>
              <br>
              thanks<br>
              Stephen<br>
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>