<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>De: </b>"Brian Goetz" <brian.goetz@oracle.com><br><b>À: </b>"Remi Forax" <forax@univ-mlv.fr><br><b>Cc: </b>"Gavin Bierman" <gavin.bierman@oracle.com>, "amber-spec-experts" <amber-spec-experts@openjdk.java.net><br><b>Envoyé: </b>Vendredi 3 Novembre 2017 21:53:50<br><b>Objet: </b>Re: Patterns design question: Primitive type tests<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><tt>Note that is really just about primitives, as they are the only
      ones whose value sets have non-trivial intersection.  Value types,
      being non-polymorphic and having no nontrivial overlap, won't have
      this problem.  </tt></blockquote><div><br data-mce-bogus="1"></div><div>I can be a mess with value-types too if there is a way to link a value-type to its box (or vice-versa like in the MVT, so we have the operation box and unbox) and boxes and value types can declare different interfaces (you can not do that with the current prototype because a value type can not declare interfaces yet), you have reproduced exactly the same issue as with primitives and their corresponding wrappers. Forcing a value type and its box to have the same set of interfaces fix the issue.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><tt>
      <br>
      Arguably, for strongly typed literals ("case 0.0f"), we could
      allow them against a target type of Object or Number, since
      there's only one type they could mean, but I don't see the
      return-on-spec-complexity here.</tt></blockquote><div><br></div><div>I agree.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><tt>
      <br>
      <br>
    </tt><br><div class="moz-cite-prefix">On 11/3/2017 4:30 PM, Remi Forax wrote:<br></div><blockquote cite="mid:117160943.2264144.1509741017437.JavaMail.zimbra@u-pem.fr"><div id="zimbraEditorContainer" style="font-family: arial,
        helvetica, sans-serif; font-size: 12pt; color: #000000" class="10"><div>I'm happy with choice #3 too.</div><div><br></div><div>#2 is a sad choice because this semantics is not explicit,<br></div><div>#2 means instanceof + unboxing + widening but nowhere in
          the syntax the wrapper type used for the instanceof and the
          unboxing appears. Not having the wrapper type mentioned
          doesn't pass my semantics smell check.<br></div><div><br></div><div>regards,<br></div><div>Rémi</div><div><br></div><hr id="zwchr"><div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>De:
            </b>"Brian Goetz" <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com" target="_blank"><brian.goetz@oracle.com></a><br><b>À: </b>"Gavin Bierman" <a class="moz-txt-link-rfc2396E" href="mailto:gavin.bierman@oracle.com" target="_blank"><gavin.bierman@oracle.com></a>,
            "amber-spec-experts"
            <a class="moz-txt-link-rfc2396E" href="mailto:amber-spec-experts@openjdk.java.net" target="_blank"><amber-spec-experts@openjdk.java.net></a><br><b>Envoyé: </b>Vendredi 3 Novembre 2017 20:37:20<br><b>Objet: </b>Re: Patterns design question: Primitive type
            tests<br></blockquote></div><div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><tt>As
              I outlined in the mail on the survey, I think there are
              three possible ways to treat primitive type test patterns
              and numeric constant patterns (when the target type is a
              reference type):<br>
              <br>
              1.  Treat them as if they were synonyms for their box
              type.  <br>
              2.  Treat them as matching a set of values; for example,
              "int x" matches integers in the traditional 32 bit range,
              unboxing numeric targets and comparing their values.<br>
              3.  Outlaw them, to avoid confusion or to preserve the
              opportunity to do either (1) or (2) later.<br>
              <br>
              For my mind, I think #2 is the "right" answer; I think #1
              would be a sad answer.  But, there are two additional
              considerations I'd add:<br>
               - As the survey showed, there would be a significant
              education component of choosing #2, and;<br>
               - There isn't really an overwhelming need for being able
              to say "Is this Object a numeric zero" or "Is this object
              a boxed primitive in the range of int."  <br>
              <br>
              Taken together, these lead me to #3 -- rather than choose
              between something sad and something that makes developers
              heads explode, just do neither.  I don't think this is a
              bad choice.  <br>
              <br>
              Concretely, what I'd propose is:<br>
              <br>
              Only allow primitive type test patterns in type-restating
              contexts.  This means that<br>
              <br>
                  switch (anObject) {<br>
                      case int x: ...<br>
                  }<br>
              <br>
              is no good -- you'd have to say Integer x or Number x or
              something more specific.  But you could say:<br>
              <br>
                  switch (anObject) {<br>
                      case Point(int x, int y): ...<br>
                  }<br>
              <br>
              because the types of the extracted components of Point are
              int, and therefore the type test pattern is type-restating
              (statically provable to match.)  <br>
              <br>
              Similarly, for numeric constant patterns, only allow them
              in switches where the target type is a primitive or a
              primitive box.  <br>
              <br>
              There are ample workarounds where the user can explicitly
              say what they want, if they need to -- but I don't think
              it will actually come up very often.  And this choice
              leaves us the option to pursue either #1 or #2 later, if
              it turns out that we underestimated how often people want
              to do this.<br>
              <br>
              This also sidesteps the question of dominance, since the
              confusing cases below (like Integer vs int) will not come
              up except in situations where we can prove they are
              equivalent.  <br>
              <br>
            </tt><br><div class="moz-cite-prefix">On 11/3/2017 6:47 AM, Gavin
              Bierman wrote:<br></div><blockquote cite="mid:DC28796E-3016-4117-8176-72E055B4FE7A@oracle.com"><h2 id="primitive-type-test-patterns" style="box-sizing:
                border-box; margin-bottom: 16px; line-height: 1.225;
                padding-bottom: 0.3em; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; margin-top: 0px
                !important;" class="">Primitive type-test patterns</h2><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">Given
                that patterns include constant expressions, and type
                tests possibly including generic types; it seems
                reasonable to consider the possibility of allowing
                primitive type tests in pattern matching. (This answers
                a sometimes-requested feature: can <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">instanceof</code> support
                primitive types?)</p><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">However,
                it is not wholly obvious what this test might mean. One
                possibility is that a “type-restating” equivalent for
                primitive type-test patterns is assignment conversion;
                e.g. if I have</p><pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">case int x:</code></pre><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">then
                a target whose static type is <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">byte</code>, <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">short</code>, <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">char</code>,
                or <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">int</code> –
                or their boxes – will be statically deemed to match.</p><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">A
                target whose <em style="box-sizing: border-box;" class="">dynamic</em> type can be assigned to the
                primitive type through a combination of unboxing and
                widening (again, assignment conversion) matches a
                primitive type test. So if we have:</p><pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">switch (o) {
    case int i: ...</code></pre><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">we
                have to do <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">instanceof</code> tests
                against {<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Integer</code>,<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Short</code>,<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Character</code>,<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Boolean</code>}
                to determine a match.</p><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">A
                primitive type test pattern dominates other primitive
                type patterns according to assingment compatibility; <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">int</code> dominates <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">byte</code>/<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">short</code>/<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">char</code>, <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">long</code> dominates <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">int</code>/<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">byte</code>/<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">short</code>/<code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">char</code>,
                and <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">double</code> dominates <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: ; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">float</code>.</p><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">A
                primitive type test pattern is inapplicable (dead) if
                cast conversion from the static type of the target
                fails:</p><pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">Map m;
switch (m) {
    case int x:  // compile error
}</code></pre><p style="box-sizing: border-box; margin-top: 0px;
                margin-bottom: 16px; color: rgb(51, 51, 51);
                font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
                Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe
                UI Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="">The
                dominance interaction between primitive type-tests and
                reference type-tests for the wrapper types (and their
                supertypes) seems messy. Consider the following
                combinations:</p><pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">case int n:
case Integer n:  // dead

case Integer n:
case int n:      // not dead -- still matches Short, Byte

case Byte b:
case byte b:     // dead

case Number n:
case int n:      // dead</code></pre><div style="box-sizing: border-box; margin-top: 0px;
                color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
                Helvetica, 'Segoe UI', Arial, freesans, sans-serif,
                'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI
                Symbol'; font-size: 16px; margin-bottom: 0px
                !important;" class="">Is there some unifying theory that
                makes sense here? One possibility is to take a more
                denotational view: a type is a set of values, so type
                restatement is really about semantic set inclusion, and
                dynamic testing is about set membership. Is this adding
                too much complexity? Do developers really care about
                this feature?</div></blockquote><br><br></blockquote></div></div></blockquote><br><br></blockquote></div></div></body></html>