<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4"><font face="monospace">The gap between exhaustiveness
        and totality (which we call "remainder") is indeed somewhat
        counterintuitive at first, because we would like for these two
        words to mean the same thing.  There were many, many discussions
        regarding this in Record Patterns.  This JEP extends the
        surprise a little bit, but only in a quantitative, not
        qualitative way; unboxing conversions are another place where we
        encounter a gap between these two similar concepts.<br>
        <br>
        The first part of the example (Box<Box<String>>) is
        not new to this JEP; this is how nested patterns work.  (If you
        think about it for long enough, you realize that the
        alternatives are all nearly intolerable.)  The
        Box<Integer> example just adds one more form of remainder.<br>
        <br>
        Imagine it worked the way your intuition tells you it should
        work.  I'll start with the old case, nested record patterns. 
        Now, suppose you have:<br>
        <br>
            record Pair<T,U>(T t, U u) { }<br>
        <br>
        ...<br>
        <br>
            Pair<Pair<A, B>, Pair<C, D>> p = ...<br>
        <br>
            switch (p) { <br>
                case Pair(Pair(A a, B b), Pair(C c, D d)): ...<br>
            }<br>
        <br>
        Under the David rules, this switch is not exhaustive, because it
        matches neither Pair(null, _) or Pair(_, null).  So what cases
        would you have to add to the switch to satisfy the compiler's
        complaints of non-exhaustiveness?  Write the code, and then tell
        me if you want to program in that language...<br>
        <br>
        <br>
        <br>
        <br>
      </font></font><br>
    <div class="moz-cite-prefix">On 9/25/2023 4:50 PM, David Alayachew
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAA9v-_M4bJpYXFC7i2yssOfyG-OwEvsB=-v6rrjz1a2R1faz6Q@mail.gmail.com">
      
      <div dir="ltr">
        <div class="gmail_default" style="font-family:monospace">Hello
          Mark,<br>
          <br>
          Thank you for posting this! I am shocked to see the Level of
          Effort set to M -- all those sharp edges makes this seem much
          more complex!<br>
          <br>
          I was very surprised to see the following snippet in the JEP.<br>
          <br>
          <br>
          > With pattern labels involving record patterns, some<br>
          > patterns are considered to be exhaustive even when they<br>
          > are not unconditional. For example:<br>
          > <br>
          > Box<Box<String>> bbs = ...<br>
          > switch (bbs) {<br>
          >     case Box(Box(String s)): ...<br>
          > }<br>
          > <br>
          > This switch is considered exhaustive on
          Box<Box<String>><br>
          > even though the pattern Box(Box(String s)) will not match<br>
          > the pathological value new Box(null), which is in the<br>
          > remainder set and is handled by a synthetic default<br>
          > clause that throws MatchException.<br>
          > <br>
          > With the introduction of primitive type patterns, we<br>
          > observe that unboxing follows the same philosophy. For<br>
          > example:<br>
          > <br>
          > Box<Integer> bi = ...<br>
          > switch (bi) {<br>
          >     case Box(int i): ...<br>
          > }<br>
          > <br>
          > This switch is considered exhaustive on
          Box<Integer> even<br>
          > though the pattern Box(int i) will not match the<br>
          > pathological value new Box(null), which is in the<br>
          > remainder set.<br>
          <br>
          This surprises me because it feels like the analogy of
          Box<Box<String>> is a poor comparison to this.
          More specifically, it feels like comparing Apples and Oranges.<br>
          <br>
          The reason I feel that way is because I have a mental model in
          my head that has the following rules.<br>
          <br>
          * If I have a top level pattern, it does not match null.
          That's what case null is for.<br>
          <br>
              * For example, case String s, I do not expect s to be
          null.<br>
          <br>
             * Because of this, I understand why a case int i would be
          considered exhaustive, it seems to follow the same rules as a
          type pattern.<br>
          <br>
          * And more specifically, the rules of exhaustiveness seem to
          align here too. If instead of case String s, I had case Foo f,
          I would assume that the pattern is exhaustive if (f) can match
          the full domain, not including null.<br>
          <br>
          * If I have a nested pattern, that pattern can match null.<br>
          <br>
              * For example, case Box(String s), I can expect s to maybe
          be null.<br>
          <br>
          * Because of this, I do not understand why a case int i would
          be considered exhaustive, because it seems to break from the
          rules of a type pattern thus far.<br>
          <br>
          * To give an example, if I have record Bar(int i), and then I
          later refactor that to be record Bar(Integer i), I would hope
          that my type pattern would no longer be exhaustive. But it
          sounds a lot like the above passage implies it WOULD be
          exhaustive.<br>
          <br>
          I do not understand this decision. Could you help me
          understand the what and the why? I also want to know your
          response to the sharp corner I raised when it comes to
          refactoring primitives to and from their boxed variants. Since
          Valhalla is on its way (hopefully bringing with it the ability
          to opt-in and opt-out of nullability), it feels like this
          sharp corner is going to protrude even further and be even
          sharper. Could you address that concern too please?<br>
          <br>
          Thank you for your time and help!<br>
          David Alayachew<br>
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Mon, Sep 25, 2023 at
          10:09 AM Mark Reinhold <<a href="mailto:mark.reinhold@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">mark.reinhold@oracle.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><a href="https://openjdk.org/jeps/455" rel="noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://openjdk.org/jeps/455</a><br>
          <br>
            Summary: Enhance pattern matching by allowing primitive type
          patterns<br>
            to be used in all pattern contexts, align the semantics of
          primitive<br>
            type patterns with that of instanceof, and extend switch to
          allow<br>
            primitive constants as case labels. This is a preview
          language feature.<br>
          <br>
          - Mark</blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>